1 //! Parallel iterator types for `IndexSet` with [rayon](https://docs.rs/rayon/1.0/rayon).
2 //!
3 //! You will rarely need to interact with this module directly unless you need to name one of the
4 //! iterator types.
5 //!
6 //! Requires crate feature `"rayon"`.
7 
8 use super::collect;
9 use rayon::iter::plumbing::{Consumer, ProducerCallback, UnindexedConsumer};
10 use rayon::prelude::*;
11 
12 use crate::vec::Vec;
13 use core::cmp::Ordering;
14 use core::fmt;
15 use core::hash::{BuildHasher, Hash};
16 use core::ops::RangeBounds;
17 
18 use crate::Entries;
19 use crate::IndexSet;
20 
21 type Bucket<T> = crate::Bucket<T, ()>;
22 
23 /// Requires crate feature `"rayon"`.
24 impl<T, S> IntoParallelIterator for IndexSet<T, S>
25 where
26     T: Send,
27 {
28     type Item = T;
29     type Iter = IntoParIter<T>;
30 
into_par_iter(self) -> Self::Iter31     fn into_par_iter(self) -> Self::Iter {
32         IntoParIter {
33             entries: self.into_entries(),
34         }
35     }
36 }
37 
38 /// A parallel owning iterator over the items of a `IndexSet`.
39 ///
40 /// This `struct` is created by the [`into_par_iter`] method on [`IndexSet`]
41 /// (provided by rayon's `IntoParallelIterator` trait). See its documentation for more.
42 ///
43 /// [`IndexSet`]: ../struct.IndexSet.html
44 /// [`into_par_iter`]: ../struct.IndexSet.html#method.into_par_iter
45 pub struct IntoParIter<T> {
46     entries: Vec<Bucket<T>>,
47 }
48 
49 impl<T: fmt::Debug> fmt::Debug for IntoParIter<T> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result50     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
51         let iter = self.entries.iter().map(Bucket::key_ref);
52         f.debug_list().entries(iter).finish()
53     }
54 }
55 
56 impl<T: Send> ParallelIterator for IntoParIter<T> {
57     type Item = T;
58 
59     parallel_iterator_methods!(Bucket::key);
60 }
61 
62 impl<T: Send> IndexedParallelIterator for IntoParIter<T> {
63     indexed_parallel_iterator_methods!(Bucket::key);
64 }
65 
66 /// Requires crate feature `"rayon"`.
67 impl<'a, T, S> IntoParallelIterator for &'a IndexSet<T, S>
68 where
69     T: Sync,
70 {
71     type Item = &'a T;
72     type Iter = ParIter<'a, T>;
73 
into_par_iter(self) -> Self::Iter74     fn into_par_iter(self) -> Self::Iter {
75         ParIter {
76             entries: self.as_entries(),
77         }
78     }
79 }
80 
81 /// A parallel iterator over the items of a `IndexSet`.
82 ///
83 /// This `struct` is created by the [`par_iter`] method on [`IndexSet`]
84 /// (provided by rayon's `IntoParallelRefIterator` trait). See its documentation for more.
85 ///
86 /// [`IndexSet`]: ../struct.IndexSet.html
87 /// [`par_iter`]: ../struct.IndexSet.html#method.par_iter
88 pub struct ParIter<'a, T> {
89     entries: &'a [Bucket<T>],
90 }
91 
92 impl<T> Clone for ParIter<'_, T> {
clone(&self) -> Self93     fn clone(&self) -> Self {
94         ParIter { ..*self }
95     }
96 }
97 
98 impl<T: fmt::Debug> fmt::Debug for ParIter<'_, T> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result99     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
100         let iter = self.entries.iter().map(Bucket::key_ref);
101         f.debug_list().entries(iter).finish()
102     }
103 }
104 
105 impl<'a, T: Sync> ParallelIterator for ParIter<'a, T> {
106     type Item = &'a T;
107 
108     parallel_iterator_methods!(Bucket::key_ref);
109 }
110 
111 impl<T: Sync> IndexedParallelIterator for ParIter<'_, T> {
112     indexed_parallel_iterator_methods!(Bucket::key_ref);
113 }
114 
115 /// Requires crate feature `"rayon"`.
116 impl<'a, T, S> ParallelDrainRange<usize> for &'a mut IndexSet<T, S>
117 where
118     T: Send,
119 {
120     type Item = T;
121     type Iter = ParDrain<'a, T>;
122 
par_drain<R: RangeBounds<usize>>(self, range: R) -> Self::Iter123     fn par_drain<R: RangeBounds<usize>>(self, range: R) -> Self::Iter {
124         ParDrain {
125             entries: self.map.core.par_drain(range),
126         }
127     }
128 }
129 
130 /// A parallel draining iterator over the items of a `IndexSet`.
131 ///
132 /// This `struct` is created by the [`par_drain`] method on [`IndexSet`]
133 /// (provided by rayon's `ParallelDrainRange` trait). See its documentation for more.
134 ///
135 /// [`par_drain`]: ../struct.IndexSet.html#method.par_drain
136 /// [`IndexSet`]: ../struct.IndexSet.html
137 pub struct ParDrain<'a, T: Send> {
138     entries: rayon::vec::Drain<'a, Bucket<T>>,
139 }
140 
141 impl<T: Send> ParallelIterator for ParDrain<'_, T> {
142     type Item = T;
143 
144     parallel_iterator_methods!(Bucket::key);
145 }
146 
147 impl<T: Send> IndexedParallelIterator for ParDrain<'_, T> {
148     indexed_parallel_iterator_methods!(Bucket::key);
149 }
150 
151 /// Parallel iterator methods and other parallel methods.
152 ///
153 /// The following methods **require crate feature `"rayon"`**.
154 ///
155 /// See also the `IntoParallelIterator` implementations.
156 impl<T, S> IndexSet<T, S>
157 where
158     T: Hash + Eq + Sync,
159     S: BuildHasher + Sync,
160 {
161     /// Return a parallel iterator over the values that are in `self` but not `other`.
162     ///
163     /// While parallel iterators can process items in any order, their relative order
164     /// in the `self` set is still preserved for operations like `reduce` and `collect`.
par_difference<'a, S2>( &'a self, other: &'a IndexSet<T, S2>, ) -> ParDifference<'a, T, S, S2> where S2: BuildHasher + Sync,165     pub fn par_difference<'a, S2>(
166         &'a self,
167         other: &'a IndexSet<T, S2>,
168     ) -> ParDifference<'a, T, S, S2>
169     where
170         S2: BuildHasher + Sync,
171     {
172         ParDifference {
173             set1: self,
174             set2: other,
175         }
176     }
177 
178     /// Return a parallel iterator over the values that are in `self` or `other`,
179     /// but not in both.
180     ///
181     /// While parallel iterators can process items in any order, their relative order
182     /// in the sets is still preserved for operations like `reduce` and `collect`.
183     /// Values from `self` are produced in their original order, followed by
184     /// values from `other` in their original order.
par_symmetric_difference<'a, S2>( &'a self, other: &'a IndexSet<T, S2>, ) -> ParSymmetricDifference<'a, T, S, S2> where S2: BuildHasher + Sync,185     pub fn par_symmetric_difference<'a, S2>(
186         &'a self,
187         other: &'a IndexSet<T, S2>,
188     ) -> ParSymmetricDifference<'a, T, S, S2>
189     where
190         S2: BuildHasher + Sync,
191     {
192         ParSymmetricDifference {
193             set1: self,
194             set2: other,
195         }
196     }
197 
198     /// Return a parallel iterator over the values that are in both `self` and `other`.
199     ///
200     /// While parallel iterators can process items in any order, their relative order
201     /// in the `self` set is still preserved for operations like `reduce` and `collect`.
par_intersection<'a, S2>( &'a self, other: &'a IndexSet<T, S2>, ) -> ParIntersection<'a, T, S, S2> where S2: BuildHasher + Sync,202     pub fn par_intersection<'a, S2>(
203         &'a self,
204         other: &'a IndexSet<T, S2>,
205     ) -> ParIntersection<'a, T, S, S2>
206     where
207         S2: BuildHasher + Sync,
208     {
209         ParIntersection {
210             set1: self,
211             set2: other,
212         }
213     }
214 
215     /// Return a parallel iterator over all values that are in `self` or `other`.
216     ///
217     /// While parallel iterators can process items in any order, their relative order
218     /// in the sets is still preserved for operations like `reduce` and `collect`.
219     /// Values from `self` are produced in their original order, followed by
220     /// values that are unique to `other` in their original order.
par_union<'a, S2>(&'a self, other: &'a IndexSet<T, S2>) -> ParUnion<'a, T, S, S2> where S2: BuildHasher + Sync,221     pub fn par_union<'a, S2>(&'a self, other: &'a IndexSet<T, S2>) -> ParUnion<'a, T, S, S2>
222     where
223         S2: BuildHasher + Sync,
224     {
225         ParUnion {
226             set1: self,
227             set2: other,
228         }
229     }
230 
231     /// Returns `true` if `self` contains all of the same values as `other`,
232     /// regardless of each set's indexed order, determined in parallel.
par_eq<S2>(&self, other: &IndexSet<T, S2>) -> bool where S2: BuildHasher + Sync,233     pub fn par_eq<S2>(&self, other: &IndexSet<T, S2>) -> bool
234     where
235         S2: BuildHasher + Sync,
236     {
237         self.len() == other.len() && self.par_is_subset(other)
238     }
239 
240     /// Returns `true` if `self` has no elements in common with `other`,
241     /// determined in parallel.
par_is_disjoint<S2>(&self, other: &IndexSet<T, S2>) -> bool where S2: BuildHasher + Sync,242     pub fn par_is_disjoint<S2>(&self, other: &IndexSet<T, S2>) -> bool
243     where
244         S2: BuildHasher + Sync,
245     {
246         if self.len() <= other.len() {
247             self.par_iter().all(move |value| !other.contains(value))
248         } else {
249             other.par_iter().all(move |value| !self.contains(value))
250         }
251     }
252 
253     /// Returns `true` if all elements of `other` are contained in `self`,
254     /// determined in parallel.
par_is_superset<S2>(&self, other: &IndexSet<T, S2>) -> bool where S2: BuildHasher + Sync,255     pub fn par_is_superset<S2>(&self, other: &IndexSet<T, S2>) -> bool
256     where
257         S2: BuildHasher + Sync,
258     {
259         other.par_is_subset(self)
260     }
261 
262     /// Returns `true` if all elements of `self` are contained in `other`,
263     /// determined in parallel.
par_is_subset<S2>(&self, other: &IndexSet<T, S2>) -> bool where S2: BuildHasher + Sync,264     pub fn par_is_subset<S2>(&self, other: &IndexSet<T, S2>) -> bool
265     where
266         S2: BuildHasher + Sync,
267     {
268         self.len() <= other.len() && self.par_iter().all(move |value| other.contains(value))
269     }
270 }
271 
272 /// A parallel iterator producing elements in the difference of `IndexSet`s.
273 ///
274 /// This `struct` is created by the [`par_difference`] method on [`IndexSet`].
275 /// See its documentation for more.
276 ///
277 /// [`IndexSet`]: ../struct.IndexSet.html
278 /// [`par_difference`]: ../struct.IndexSet.html#method.par_difference
279 pub struct ParDifference<'a, T, S1, S2> {
280     set1: &'a IndexSet<T, S1>,
281     set2: &'a IndexSet<T, S2>,
282 }
283 
284 impl<T, S1, S2> Clone for ParDifference<'_, T, S1, S2> {
clone(&self) -> Self285     fn clone(&self) -> Self {
286         ParDifference { ..*self }
287     }
288 }
289 
290 impl<T, S1, S2> fmt::Debug for ParDifference<'_, T, S1, S2>
291 where
292     T: fmt::Debug + Eq + Hash,
293     S1: BuildHasher,
294     S2: BuildHasher,
295 {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result296     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
297         f.debug_list()
298             .entries(self.set1.difference(self.set2))
299             .finish()
300     }
301 }
302 
303 impl<'a, T, S1, S2> ParallelIterator for ParDifference<'a, T, S1, S2>
304 where
305     T: Hash + Eq + Sync,
306     S1: BuildHasher + Sync,
307     S2: BuildHasher + Sync,
308 {
309     type Item = &'a T;
310 
drive_unindexed<C>(self, consumer: C) -> C::Result where C: UnindexedConsumer<Self::Item>,311     fn drive_unindexed<C>(self, consumer: C) -> C::Result
312     where
313         C: UnindexedConsumer<Self::Item>,
314     {
315         let Self { set1, set2 } = self;
316 
317         set1.par_iter()
318             .filter(move |&item| !set2.contains(item))
319             .drive_unindexed(consumer)
320     }
321 }
322 
323 /// A parallel iterator producing elements in the intersection of `IndexSet`s.
324 ///
325 /// This `struct` is created by the [`par_intersection`] method on [`IndexSet`].
326 /// See its documentation for more.
327 ///
328 /// [`IndexSet`]: ../struct.IndexSet.html
329 /// [`par_intersection`]: ../struct.IndexSet.html#method.par_intersection
330 pub struct ParIntersection<'a, T, S1, S2> {
331     set1: &'a IndexSet<T, S1>,
332     set2: &'a IndexSet<T, S2>,
333 }
334 
335 impl<T, S1, S2> Clone for ParIntersection<'_, T, S1, S2> {
clone(&self) -> Self336     fn clone(&self) -> Self {
337         ParIntersection { ..*self }
338     }
339 }
340 
341 impl<T, S1, S2> fmt::Debug for ParIntersection<'_, T, S1, S2>
342 where
343     T: fmt::Debug + Eq + Hash,
344     S1: BuildHasher,
345     S2: BuildHasher,
346 {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result347     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
348         f.debug_list()
349             .entries(self.set1.intersection(self.set2))
350             .finish()
351     }
352 }
353 
354 impl<'a, T, S1, S2> ParallelIterator for ParIntersection<'a, T, S1, S2>
355 where
356     T: Hash + Eq + Sync,
357     S1: BuildHasher + Sync,
358     S2: BuildHasher + Sync,
359 {
360     type Item = &'a T;
361 
drive_unindexed<C>(self, consumer: C) -> C::Result where C: UnindexedConsumer<Self::Item>,362     fn drive_unindexed<C>(self, consumer: C) -> C::Result
363     where
364         C: UnindexedConsumer<Self::Item>,
365     {
366         let Self { set1, set2 } = self;
367 
368         set1.par_iter()
369             .filter(move |&item| set2.contains(item))
370             .drive_unindexed(consumer)
371     }
372 }
373 
374 /// A parallel iterator producing elements in the symmetric difference of `IndexSet`s.
375 ///
376 /// This `struct` is created by the [`par_symmetric_difference`] method on
377 /// [`IndexSet`]. See its documentation for more.
378 ///
379 /// [`IndexSet`]: ../struct.IndexSet.html
380 /// [`par_symmetric_difference`]: ../struct.IndexSet.html#method.par_symmetric_difference
381 pub struct ParSymmetricDifference<'a, T, S1, S2> {
382     set1: &'a IndexSet<T, S1>,
383     set2: &'a IndexSet<T, S2>,
384 }
385 
386 impl<T, S1, S2> Clone for ParSymmetricDifference<'_, T, S1, S2> {
clone(&self) -> Self387     fn clone(&self) -> Self {
388         ParSymmetricDifference { ..*self }
389     }
390 }
391 
392 impl<T, S1, S2> fmt::Debug for ParSymmetricDifference<'_, T, S1, S2>
393 where
394     T: fmt::Debug + Eq + Hash,
395     S1: BuildHasher,
396     S2: BuildHasher,
397 {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result398     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
399         f.debug_list()
400             .entries(self.set1.symmetric_difference(self.set2))
401             .finish()
402     }
403 }
404 
405 impl<'a, T, S1, S2> ParallelIterator for ParSymmetricDifference<'a, T, S1, S2>
406 where
407     T: Hash + Eq + Sync,
408     S1: BuildHasher + Sync,
409     S2: BuildHasher + Sync,
410 {
411     type Item = &'a T;
412 
drive_unindexed<C>(self, consumer: C) -> C::Result where C: UnindexedConsumer<Self::Item>,413     fn drive_unindexed<C>(self, consumer: C) -> C::Result
414     where
415         C: UnindexedConsumer<Self::Item>,
416     {
417         let Self { set1, set2 } = self;
418 
419         set1.par_difference(set2)
420             .chain(set2.par_difference(set1))
421             .drive_unindexed(consumer)
422     }
423 }
424 
425 /// A parallel iterator producing elements in the union of `IndexSet`s.
426 ///
427 /// This `struct` is created by the [`par_union`] method on [`IndexSet`].
428 /// See its documentation for more.
429 ///
430 /// [`IndexSet`]: ../struct.IndexSet.html
431 /// [`par_union`]: ../struct.IndexSet.html#method.par_union
432 pub struct ParUnion<'a, T, S1, S2> {
433     set1: &'a IndexSet<T, S1>,
434     set2: &'a IndexSet<T, S2>,
435 }
436 
437 impl<T, S1, S2> Clone for ParUnion<'_, T, S1, S2> {
clone(&self) -> Self438     fn clone(&self) -> Self {
439         ParUnion { ..*self }
440     }
441 }
442 
443 impl<T, S1, S2> fmt::Debug for ParUnion<'_, T, S1, S2>
444 where
445     T: fmt::Debug + Eq + Hash,
446     S1: BuildHasher,
447     S2: BuildHasher,
448 {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result449     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
450         f.debug_list().entries(self.set1.union(self.set2)).finish()
451     }
452 }
453 
454 impl<'a, T, S1, S2> ParallelIterator for ParUnion<'a, T, S1, S2>
455 where
456     T: Hash + Eq + Sync,
457     S1: BuildHasher + Sync,
458     S2: BuildHasher + Sync,
459 {
460     type Item = &'a T;
461 
drive_unindexed<C>(self, consumer: C) -> C::Result where C: UnindexedConsumer<Self::Item>,462     fn drive_unindexed<C>(self, consumer: C) -> C::Result
463     where
464         C: UnindexedConsumer<Self::Item>,
465     {
466         let Self { set1, set2 } = self;
467 
468         set1.par_iter()
469             .chain(set2.par_difference(set1))
470             .drive_unindexed(consumer)
471     }
472 }
473 
474 /// Parallel sorting methods.
475 ///
476 /// The following methods **require crate feature `"rayon"`**.
477 impl<T, S> IndexSet<T, S>
478 where
479     T: Hash + Eq + Send,
480     S: BuildHasher + Send,
481 {
482     /// Sort the set’s values in parallel by their default ordering.
par_sort(&mut self) where T: Ord,483     pub fn par_sort(&mut self)
484     where
485         T: Ord,
486     {
487         self.with_entries(|entries| {
488             entries.par_sort_by(|a, b| T::cmp(&a.key, &b.key));
489         });
490     }
491 
492     /// Sort the set’s values in place and in parallel, using the comparison function `cmp`.
par_sort_by<F>(&mut self, cmp: F) where F: Fn(&T, &T) -> Ordering + Sync,493     pub fn par_sort_by<F>(&mut self, cmp: F)
494     where
495         F: Fn(&T, &T) -> Ordering + Sync,
496     {
497         self.with_entries(|entries| {
498             entries.par_sort_by(move |a, b| cmp(&a.key, &b.key));
499         });
500     }
501 
502     /// Sort the values of the set in parallel and return a by-value parallel iterator of
503     /// the values with the result.
par_sorted_by<F>(self, cmp: F) -> IntoParIter<T> where F: Fn(&T, &T) -> Ordering + Sync,504     pub fn par_sorted_by<F>(self, cmp: F) -> IntoParIter<T>
505     where
506         F: Fn(&T, &T) -> Ordering + Sync,
507     {
508         let mut entries = self.into_entries();
509         entries.par_sort_by(move |a, b| cmp(&a.key, &b.key));
510         IntoParIter { entries }
511     }
512 
513     /// Sort the set's values in parallel by their default ordering.
par_sort_unstable(&mut self) where T: Ord,514     pub fn par_sort_unstable(&mut self)
515     where
516         T: Ord,
517     {
518         self.with_entries(|entries| {
519             entries.par_sort_unstable_by(|a, b| T::cmp(&a.key, &b.key));
520         });
521     }
522 
523     /// Sort the set’s values in place and in parallel, using the comparison function `cmp`.
par_sort_unstable_by<F>(&mut self, cmp: F) where F: Fn(&T, &T) -> Ordering + Sync,524     pub fn par_sort_unstable_by<F>(&mut self, cmp: F)
525     where
526         F: Fn(&T, &T) -> Ordering + Sync,
527     {
528         self.with_entries(|entries| {
529             entries.par_sort_unstable_by(move |a, b| cmp(&a.key, &b.key));
530         });
531     }
532 
533     /// Sort the values of the set in parallel and return a by-value parallel iterator of
534     /// the values with the result.
par_sorted_unstable_by<F>(self, cmp: F) -> IntoParIter<T> where F: Fn(&T, &T) -> Ordering + Sync,535     pub fn par_sorted_unstable_by<F>(self, cmp: F) -> IntoParIter<T>
536     where
537         F: Fn(&T, &T) -> Ordering + Sync,
538     {
539         let mut entries = self.into_entries();
540         entries.par_sort_unstable_by(move |a, b| cmp(&a.key, &b.key));
541         IntoParIter { entries }
542     }
543 }
544 
545 /// Requires crate feature `"rayon"`.
546 impl<T, S> FromParallelIterator<T> for IndexSet<T, S>
547 where
548     T: Eq + Hash + Send,
549     S: BuildHasher + Default + Send,
550 {
from_par_iter<I>(iter: I) -> Self where I: IntoParallelIterator<Item = T>,551     fn from_par_iter<I>(iter: I) -> Self
552     where
553         I: IntoParallelIterator<Item = T>,
554     {
555         let list = collect(iter);
556         let len = list.iter().map(Vec::len).sum();
557         let mut set = Self::with_capacity_and_hasher(len, S::default());
558         for vec in list {
559             set.extend(vec);
560         }
561         set
562     }
563 }
564 
565 /// Requires crate feature `"rayon"`.
566 impl<T, S> ParallelExtend<T> for IndexSet<T, S>
567 where
568     T: Eq + Hash + Send,
569     S: BuildHasher + Send,
570 {
par_extend<I>(&mut self, iter: I) where I: IntoParallelIterator<Item = T>,571     fn par_extend<I>(&mut self, iter: I)
572     where
573         I: IntoParallelIterator<Item = T>,
574     {
575         for vec in collect(iter) {
576             self.extend(vec);
577         }
578     }
579 }
580 
581 /// Requires crate feature `"rayon"`.
582 impl<'a, T: 'a, S> ParallelExtend<&'a T> for IndexSet<T, S>
583 where
584     T: Copy + Eq + Hash + Send + Sync,
585     S: BuildHasher + Send,
586 {
par_extend<I>(&mut self, iter: I) where I: IntoParallelIterator<Item = &'a T>,587     fn par_extend<I>(&mut self, iter: I)
588     where
589         I: IntoParallelIterator<Item = &'a T>,
590     {
591         for vec in collect(iter) {
592             self.extend(vec);
593         }
594     }
595 }
596 
597 #[cfg(test)]
598 mod tests {
599     use super::*;
600 
601     #[test]
insert_order()602     fn insert_order() {
603         let insert = [0, 4, 2, 12, 8, 7, 11, 5, 3, 17, 19, 22, 23];
604         let mut set = IndexSet::new();
605 
606         for &elt in &insert {
607             set.insert(elt);
608         }
609 
610         assert_eq!(set.par_iter().count(), set.len());
611         assert_eq!(set.par_iter().count(), insert.len());
612         insert.par_iter().zip(&set).for_each(|(a, b)| {
613             assert_eq!(a, b);
614         });
615         (0..insert.len())
616             .into_par_iter()
617             .zip(&set)
618             .for_each(|(i, v)| {
619                 assert_eq!(set.get_index(i).unwrap(), v);
620             });
621     }
622 
623     #[test]
partial_eq_and_eq()624     fn partial_eq_and_eq() {
625         let mut set_a = IndexSet::new();
626         set_a.insert(1);
627         set_a.insert(2);
628         let mut set_b = set_a.clone();
629         assert!(set_a.par_eq(&set_b));
630         set_b.swap_remove(&1);
631         assert!(!set_a.par_eq(&set_b));
632         set_b.insert(3);
633         assert!(!set_a.par_eq(&set_b));
634 
635         let set_c: IndexSet<_> = set_b.into_par_iter().collect();
636         assert!(!set_a.par_eq(&set_c));
637         assert!(!set_c.par_eq(&set_a));
638     }
639 
640     #[test]
extend()641     fn extend() {
642         let mut set = IndexSet::new();
643         set.par_extend(vec![&1, &2, &3, &4]);
644         set.par_extend(vec![5, 6]);
645         assert_eq!(
646             set.into_par_iter().collect::<Vec<_>>(),
647             vec![1, 2, 3, 4, 5, 6]
648         );
649     }
650 
651     #[test]
comparisons()652     fn comparisons() {
653         let set_a: IndexSet<_> = (0..3).collect();
654         let set_b: IndexSet<_> = (3..6).collect();
655         let set_c: IndexSet<_> = (0..6).collect();
656         let set_d: IndexSet<_> = (3..9).collect();
657 
658         assert!(!set_a.par_is_disjoint(&set_a));
659         assert!(set_a.par_is_subset(&set_a));
660         assert!(set_a.par_is_superset(&set_a));
661 
662         assert!(set_a.par_is_disjoint(&set_b));
663         assert!(set_b.par_is_disjoint(&set_a));
664         assert!(!set_a.par_is_subset(&set_b));
665         assert!(!set_b.par_is_subset(&set_a));
666         assert!(!set_a.par_is_superset(&set_b));
667         assert!(!set_b.par_is_superset(&set_a));
668 
669         assert!(!set_a.par_is_disjoint(&set_c));
670         assert!(!set_c.par_is_disjoint(&set_a));
671         assert!(set_a.par_is_subset(&set_c));
672         assert!(!set_c.par_is_subset(&set_a));
673         assert!(!set_a.par_is_superset(&set_c));
674         assert!(set_c.par_is_superset(&set_a));
675 
676         assert!(!set_c.par_is_disjoint(&set_d));
677         assert!(!set_d.par_is_disjoint(&set_c));
678         assert!(!set_c.par_is_subset(&set_d));
679         assert!(!set_d.par_is_subset(&set_c));
680         assert!(!set_c.par_is_superset(&set_d));
681         assert!(!set_d.par_is_superset(&set_c));
682     }
683 
684     #[test]
iter_comparisons()685     fn iter_comparisons() {
686         use std::iter::empty;
687 
688         fn check<'a, I1, I2>(iter1: I1, iter2: I2)
689         where
690             I1: ParallelIterator<Item = &'a i32>,
691             I2: Iterator<Item = i32>,
692         {
693             let v1: Vec<_> = iter1.copied().collect();
694             let v2: Vec<_> = iter2.collect();
695             assert_eq!(v1, v2);
696         }
697 
698         let set_a: IndexSet<_> = (0..3).collect();
699         let set_b: IndexSet<_> = (3..6).collect();
700         let set_c: IndexSet<_> = (0..6).collect();
701         let set_d: IndexSet<_> = (3..9).rev().collect();
702 
703         check(set_a.par_difference(&set_a), empty());
704         check(set_a.par_symmetric_difference(&set_a), empty());
705         check(set_a.par_intersection(&set_a), 0..3);
706         check(set_a.par_union(&set_a), 0..3);
707 
708         check(set_a.par_difference(&set_b), 0..3);
709         check(set_b.par_difference(&set_a), 3..6);
710         check(set_a.par_symmetric_difference(&set_b), 0..6);
711         check(set_b.par_symmetric_difference(&set_a), (3..6).chain(0..3));
712         check(set_a.par_intersection(&set_b), empty());
713         check(set_b.par_intersection(&set_a), empty());
714         check(set_a.par_union(&set_b), 0..6);
715         check(set_b.par_union(&set_a), (3..6).chain(0..3));
716 
717         check(set_a.par_difference(&set_c), empty());
718         check(set_c.par_difference(&set_a), 3..6);
719         check(set_a.par_symmetric_difference(&set_c), 3..6);
720         check(set_c.par_symmetric_difference(&set_a), 3..6);
721         check(set_a.par_intersection(&set_c), 0..3);
722         check(set_c.par_intersection(&set_a), 0..3);
723         check(set_a.par_union(&set_c), 0..6);
724         check(set_c.par_union(&set_a), 0..6);
725 
726         check(set_c.par_difference(&set_d), 0..3);
727         check(set_d.par_difference(&set_c), (6..9).rev());
728         check(
729             set_c.par_symmetric_difference(&set_d),
730             (0..3).chain((6..9).rev()),
731         );
732         check(
733             set_d.par_symmetric_difference(&set_c),
734             (6..9).rev().chain(0..3),
735         );
736         check(set_c.par_intersection(&set_d), 3..6);
737         check(set_d.par_intersection(&set_c), (3..6).rev());
738         check(set_c.par_union(&set_d), (0..6).chain((6..9).rev()));
739         check(set_d.par_union(&set_c), (3..9).rev().chain(0..3));
740     }
741 }
742