1use either::Either;
29use itertools::Itertools;
30use rayon::prelude::*;
31use std::cmp::Ordering;
32
33use itertools::structs as it;
34use rayon::iter as ri;
35use std::iter as si;
36
37use crate::CondIterator::*;
38
39pub enum CondIterator<P, S>
51where
52 P: ParallelIterator,
53 S: Iterator<Item = P::Item>,
54{
55 Parallel(P),
56 Serial(S),
57}
58
59impl<P, S> CondIterator<P, S>
60where
61 P: ParallelIterator,
62 S: Iterator<Item = P::Item>,
63{
64 pub fn new<I>(iterable: I, parallel: bool) -> Self
65 where
66 I: IntoParallelIterator<Iter = P, Item = P::Item>
67 + IntoIterator<IntoIter = S, Item = S::Item>,
68 {
69 if parallel {
70 Self::from_parallel(iterable)
71 } else {
72 Self::from_serial(iterable)
73 }
74 }
75
76 pub fn from_parallel<I>(iterable: I) -> Self
77 where
78 I: IntoParallelIterator<Iter = P, Item = P::Item>,
79 {
80 Parallel(iterable.into_par_iter())
81 }
82
83 pub fn from_serial<I>(iterable: I) -> Self
84 where
85 I: IntoIterator<IntoIter = S, Item = S::Item>,
86 {
87 Serial(iterable.into_iter())
88 }
89
90 pub fn is_parallel(&self) -> bool {
91 matches!(self, Parallel(_))
92 }
93
94 pub fn is_serial(&self) -> bool {
95 matches!(self, Serial(_))
96 }
97}
98
99impl<P, S> CondIterator<P, S>
100where
101 P: ParallelIterator,
102 S: Iterator<Item = P::Item> + Send,
103{
104 pub fn into_parallel(self) -> Either<P, ri::IterBridge<S>> {
105 match self {
106 Parallel(iter) => Either::Left(iter),
107 Serial(iter) => Either::Right(iter.par_bridge()),
108 }
109 }
110}
111
112macro_rules! either {
113 ($self:ident, $pattern:pat => $result:expr) => {
114 match $self {
115 Parallel($pattern) => $result,
116 Serial($pattern) => $result,
117 }
118 };
119}
120
121macro_rules! wrap_either {
122 ($self:ident, $pattern:pat => $result:expr) => {
123 match $self {
124 Parallel($pattern) => Parallel($result),
125 Serial($pattern) => Serial($result),
126 }
127 };
128}
129
130impl<P, S> CondIterator<P, S>
131where
132 P: ParallelIterator,
133 S: Iterator<Item = P::Item>,
134{
135 pub fn for_each<OP>(self, op: OP)
136 where
137 OP: Fn(P::Item) + Sync + Send,
138 {
139 either!(self, iter => iter.for_each(op))
140 }
141
142 pub fn for_each_with<OP, T>(self, mut init: T, op: OP)
143 where
144 OP: Fn(&mut T, P::Item) + Sync + Send,
145 T: Send + Clone,
146 {
147 match self {
148 Parallel(iter) => iter.for_each_with(init, op),
149 Serial(iter) => iter.for_each(move |item| op(&mut init, item)),
150 }
151 }
152
153 pub fn for_each_init<OP, INIT, T>(self, init: INIT, op: OP)
154 where
155 OP: Fn(&mut T, P::Item) + Sync + Send,
156 INIT: Fn() -> T + Sync + Send,
157 {
158 match self {
159 Parallel(iter) => iter.for_each_init(init, op),
160 Serial(iter) => {
161 let mut init = init();
162 iter.for_each(move |item| op(&mut init, item))
163 }
164 }
165 }
166
167 pub fn count(self) -> usize {
168 either!(self, iter => iter.count())
169 }
170
171 pub fn map<F, R>(self, map_op: F) -> CondIterator<ri::Map<P, F>, si::Map<S, F>>
172 where
173 F: Fn(P::Item) -> R + Sync + Send,
174 R: Send,
175 {
176 wrap_either!(self, iter => iter.map(map_op))
177 }
178
179 pub fn map_with<F, T, R>(
182 self,
183 mut init: T,
184 map_op: F,
185 ) -> CondIterator<ri::MapWith<P, T, F>, si::Map<S, impl FnMut(P::Item) -> R>>
186 where
187 F: Fn(&mut T, P::Item) -> R + Sync + Send,
188 T: Send + Clone,
189 R: Send,
190 {
191 match self {
192 Parallel(iter) => Parallel(iter.map_with(init, map_op)),
193 Serial(iter) => Serial(iter.map(move |item| map_op(&mut init, item))),
194 }
195 }
196
197 pub fn map_init<F, INIT, T, R>(
200 self,
201 init: INIT,
202 map_op: F,
203 ) -> CondIterator<ri::MapInit<P, INIT, F>, si::Map<S, impl FnMut(P::Item) -> R>>
204 where
205 F: Fn(&mut T, P::Item) -> R + Sync + Send,
206 INIT: Fn() -> T + Sync + Send,
207 R: Send,
208 {
209 match self {
210 Parallel(iter) => Parallel(iter.map_init(init, map_op)),
211 Serial(iter) => {
212 let mut init = init();
213 Serial(iter.map(move |item| map_op(&mut init, item)))
214 }
215 }
216 }
217
218 pub fn cloned<'a, T>(self) -> CondIterator<ri::Cloned<P>, si::Cloned<S>>
219 where
220 T: 'a + Clone + Sync + Send,
221 P: ParallelIterator<Item = &'a T>,
222 S: Iterator<Item = &'a T>,
223 {
224 wrap_either!(self, iter => iter.cloned())
225 }
226
227 pub fn copied<'a, T>(self) -> CondIterator<ri::Copied<P>, si::Copied<S>>
228 where
229 T: 'a + Copy + Sync + Send,
230 P: ParallelIterator<Item = &'a T>,
231 S: Iterator<Item = &'a T>,
232 {
233 wrap_either!(self, iter => iter.copied())
234 }
235
236 pub fn inspect<OP>(self, inspect_op: OP) -> CondIterator<ri::Inspect<P, OP>, si::Inspect<S, OP>>
237 where
238 OP: Fn(&P::Item) + Sync + Send,
239 {
240 wrap_either!(self, iter => iter.inspect(inspect_op))
241 }
242
243 pub fn update<OP>(self, update_op: OP) -> CondIterator<ri::Update<P, OP>, it::Update<S, OP>>
244 where
245 OP: Fn(&mut P::Item) + Sync + Send,
246 {
247 wrap_either!(self, iter => iter.update(update_op))
248 }
249
250 pub fn filter<Pred>(
251 self,
252 filter_op: Pred,
253 ) -> CondIterator<ri::Filter<P, Pred>, si::Filter<S, Pred>>
254 where
255 Pred: Fn(&P::Item) -> bool + Sync + Send,
256 {
257 wrap_either!(self, iter => iter.filter(filter_op))
258 }
259
260 pub fn filter_map<Pred, R>(
261 self,
262 filter_op: Pred,
263 ) -> CondIterator<ri::FilterMap<P, Pred>, si::FilterMap<S, Pred>>
264 where
265 Pred: Fn(P::Item) -> Option<R> + Sync + Send,
266 R: Send,
267 {
268 wrap_either!(self, iter => iter.filter_map(filter_op))
269 }
270
271 pub fn flat_map<F, I>(self, map_op: F) -> CondIterator<ri::FlatMap<P, F>, si::FlatMap<S, I, F>>
272 where
273 F: Fn(P::Item) -> I + Sync + Send,
274 I: IntoParallelIterator + IntoIterator<Item = <I as IntoParallelIterator>::Item>,
275 {
276 wrap_either!(self, iter => iter.flat_map(map_op))
277 }
278
279 pub fn flat_map_iter<F, I>(
280 self,
281 map_op: F,
282 ) -> CondIterator<ri::FlatMapIter<P, F>, si::FlatMap<S, I, F>>
283 where
284 F: Fn(P::Item) -> I + Sync + Send,
285 I: IntoIterator,
286 I::Item: Send,
287 {
288 match self {
289 Parallel(iter) => Parallel(iter.flat_map_iter(map_op)),
290 Serial(iter) => Serial(iter.flat_map(map_op)),
291 }
292 }
293
294 pub fn flatten(self) -> CondIterator<ri::Flatten<P>, si::Flatten<S>>
295 where
296 P::Item: IntoParallelIterator,
297 S::Item: IntoIterator<Item = <P::Item as IntoParallelIterator>::Item>,
298 {
299 wrap_either!(self, iter => iter.flatten())
300 }
301
302 pub fn flatten_iter(self) -> CondIterator<ri::FlattenIter<P>, si::Flatten<S>>
303 where
304 P::Item: IntoIterator,
305 <P::Item as IntoIterator>::Item: Send,
306 {
307 match self {
308 Parallel(iter) => Parallel(iter.flatten_iter()),
309 Serial(iter) => Serial(iter.flatten()),
310 }
311 }
312
313 pub fn reduce<OP, ID>(self, identity: ID, op: OP) -> P::Item
314 where
315 OP: Fn(P::Item, P::Item) -> P::Item + Sync + Send,
316 ID: Fn() -> P::Item + Sync + Send,
317 {
318 match self {
319 Parallel(iter) => iter.reduce(identity, op),
320 Serial(iter) => iter.fold(identity(), op),
321 }
322 }
323
324 pub fn reduce_with<OP>(self, op: OP) -> Option<P::Item>
325 where
326 OP: Fn(P::Item, P::Item) -> P::Item + Sync + Send,
327 {
328 match self {
329 Parallel(iter) => iter.reduce_with(op),
330 Serial(iter) => iter.reduce(op),
331 }
332 }
333
334 pub fn fold<T, ID, F>(
336 self,
337 identity: ID,
338 fold_op: F,
339 ) -> CondIterator<ri::Fold<P, ID, F>, si::Once<T>>
340 where
341 F: Fn(T, P::Item) -> T + Sync + Send,
342 ID: Fn() -> T + Sync + Send,
343 T: Send,
344 {
345 match self {
346 Parallel(iter) => Parallel(iter.fold(identity, fold_op)),
347 Serial(iter) => Serial(si::once(iter.fold(identity(), fold_op))),
348 }
349 }
350
351 pub fn fold_with<F, T>(
352 self,
353 init: T,
354 fold_op: F,
355 ) -> CondIterator<ri::FoldWith<P, T, F>, si::Once<T>>
356 where
357 F: Fn(T, P::Item) -> T + Sync + Send,
358 T: Send + Clone,
359 {
360 match self {
361 Parallel(iter) => Parallel(iter.fold_with(init, fold_op)),
362 Serial(iter) => Serial(si::once(iter.fold(init, fold_op))),
363 }
364 }
365
366 pub fn sum<Sum>(self) -> Sum
367 where
368 Sum: Send + si::Sum<P::Item> + si::Sum<Sum>,
369 {
370 either!(self, iter => iter.sum())
371 }
372
373 pub fn product<Product>(self) -> Product
374 where
375 Product: Send + si::Product<P::Item> + si::Product<Product>,
376 {
377 either!(self, iter => iter.product())
378 }
379
380 pub fn min(self) -> Option<P::Item>
381 where
382 P::Item: Ord,
383 {
384 either!(self, iter => iter.min())
385 }
386
387 pub fn min_by<F>(self, f: F) -> Option<P::Item>
388 where
389 F: Sync + Send + Fn(&P::Item, &P::Item) -> Ordering,
390 {
391 either!(self, iter => iter.min_by(f))
392 }
393
394 pub fn min_by_key<K, F>(self, f: F) -> Option<P::Item>
395 where
396 K: Ord + Send,
397 F: Sync + Send + Fn(&P::Item) -> K,
398 {
399 either!(self, iter => iter.min_by_key(f))
400 }
401
402 pub fn max(self) -> Option<P::Item>
403 where
404 P::Item: Ord,
405 {
406 either!(self, iter => iter.max())
407 }
408
409 pub fn max_by<F>(self, f: F) -> Option<P::Item>
410 where
411 F: Sync + Send + Fn(&P::Item, &P::Item) -> Ordering,
412 {
413 either!(self, iter => iter.max_by(f))
414 }
415
416 pub fn max_by_key<K, F>(self, f: F) -> Option<P::Item>
417 where
418 K: Ord + Send,
419 F: Sync + Send + Fn(&P::Item) -> K,
420 {
421 either!(self, iter => iter.max_by_key(f))
422 }
423
424 pub fn chain<C>(
425 self,
426 chain: C,
427 ) -> CondIterator<ri::Chain<P, C::Iter>, si::Chain<S, C::IntoIter>>
428 where
429 C: IntoParallelIterator<Item = P::Item> + IntoIterator<Item = P::Item>,
430 {
431 wrap_either!(self, iter => iter.chain(chain))
432 }
433
434 pub fn find_any<Pred>(self, predicate: Pred) -> Option<P::Item>
435 where
436 Pred: Fn(&P::Item) -> bool + Sync + Send,
437 {
438 match self {
439 Parallel(iter) => iter.find_any(predicate),
440 Serial(mut iter) => iter.find(predicate),
441 }
442 }
443
444 pub fn find_first<Pred>(self, predicate: Pred) -> Option<P::Item>
445 where
446 Pred: Fn(&P::Item) -> bool + Sync + Send,
447 {
448 match self {
449 Parallel(iter) => iter.find_first(predicate),
450 Serial(mut iter) => iter.find(predicate),
451 }
452 }
453
454 pub fn any<Pred>(self, predicate: Pred) -> bool
455 where
456 Pred: Fn(P::Item) -> bool + Sync + Send,
457 {
458 match self {
459 Parallel(iter) => iter.any(predicate),
460 Serial(mut iter) => iter.any(predicate),
461 }
462 }
463
464 pub fn all<Pred>(self, predicate: Pred) -> bool
465 where
466 Pred: Fn(P::Item) -> bool + Sync + Send,
467 {
468 match self {
469 Parallel(iter) => iter.all(predicate),
470 Serial(mut iter) => iter.all(predicate),
471 }
472 }
473
474 pub fn while_some<T>(self) -> CondIterator<ri::WhileSome<P>, it::WhileSome<S>>
475 where
476 P: ParallelIterator<Item = Option<T>>,
477 S: Iterator<Item = Option<T>>,
478 T: Send,
479 {
480 wrap_either!(self, iter => iter.while_some())
481 }
482
483 pub fn collect<C>(self) -> C
484 where
485 C: FromCondIterator<P::Item>,
486 {
487 either!(self, iter => iter.collect())
488 }
489
490 pub fn unzip<A, B, FromA, FromB>(self) -> (FromA, FromB)
491 where
492 P: ParallelIterator<Item = (A, B)>,
493 S: Iterator<Item = (A, B)>,
494 FromA: Default + Send + CondExtend<A>,
495 FromB: Default + Send + CondExtend<B>,
496 A: Send,
497 B: Send,
498 {
499 either!(self, iter => iter.unzip())
500 }
501
502 pub fn partition<A, B, Pred>(self, predicate: Pred) -> (A, B)
505 where
506 A: Default + Send + CondExtend<P::Item>,
507 B: Default + Send + CondExtend<P::Item>,
508 Pred: Fn(&P::Item) -> bool + Sync + Send,
509 {
510 match self {
511 Parallel(iter) => iter.partition(predicate),
512 Serial(iter) => iter.partition_map(|item| {
513 if predicate(&item) {
514 Either::Left(item)
515 } else {
516 Either::Right(item)
517 }
518 }),
519 }
520 }
521
522 pub fn partition_map<A, B, Pred, L, R>(self, predicate: Pred) -> (A, B)
523 where
524 A: Default + Send + CondExtend<L>,
525 B: Default + Send + CondExtend<R>,
526 Pred: Fn(P::Item) -> Either<L, R> + Sync + Send,
527 L: Send,
528 R: Send,
529 {
530 either!(self, iter => iter.partition_map(predicate))
531 }
532
533 pub fn intersperse(
534 self,
535 element: P::Item,
536 ) -> CondIterator<ri::Intersperse<P>, it::Intersperse<S>>
537 where
538 P::Item: Clone,
539 {
540 match self {
541 Parallel(iter) => Parallel(iter.intersperse(element)),
542 Serial(iter) => Serial(Itertools::intersperse(iter, element)),
543 }
544 }
545
546 pub fn opt_len(&self) -> Option<usize> {
547 match self {
548 Parallel(ref iter) => iter.opt_len(),
549 Serial(ref iter) => match iter.size_hint() {
550 (lo, Some(hi)) if lo == hi => Some(lo),
551 _ => None,
552 },
553 }
554 }
555}
556
557impl<P, S> CondIterator<P, S>
558where
559 P: ParallelIterator,
560 S: DoubleEndedIterator<Item = P::Item>,
561{
562 pub fn find_last<Pred>(self, predicate: Pred) -> Option<P::Item>
563 where
564 Pred: Fn(&P::Item) -> bool + Sync + Send,
565 {
566 match self {
567 Parallel(iter) => iter.find_last(predicate),
568 Serial(mut iter) => iter.rfind(predicate),
569 }
570 }
571}
572
573impl<P, S> CondIterator<P, S>
574where
575 P: IndexedParallelIterator,
576 S: Iterator<Item = P::Item>,
577{
578 pub fn collect_into_vec(self, target: &mut Vec<P::Item>) {
579 match self {
580 Parallel(iter) => iter.collect_into_vec(target),
581 Serial(iter) => {
582 target.clear();
583 let (lower, _) = iter.size_hint();
584 target.reserve(lower);
585 target.extend(iter);
586 }
587 }
588 }
589
590 pub fn unzip_into_vecs<A, B>(self, left: &mut Vec<A>, right: &mut Vec<B>)
591 where
592 P: IndexedParallelIterator<Item = (A, B)>,
593 S: Iterator<Item = (A, B)>,
594 A: Send,
595 B: Send,
596 {
597 match self {
598 Parallel(iter) => iter.unzip_into_vecs(left, right),
599 Serial(iter) => {
600 left.clear();
601 right.clear();
602 let (lower, _) = iter.size_hint();
603 left.reserve(lower);
604 right.reserve(lower);
605 iter.for_each(|(a, b)| {
606 left.push(a);
607 right.push(b);
608 })
609 }
610 }
611 }
612
613 pub fn zip<Z>(self, other: Z) -> CondIterator<ri::Zip<P, Z::Iter>, si::Zip<S, Z::IntoIter>>
614 where
615 Z: IntoParallelIterator + IntoIterator<Item = <Z as IntoParallelIterator>::Item>,
616 Z::Iter: IndexedParallelIterator,
617 {
618 wrap_either!(self, iter => iter.zip(other))
619 }
620
621 pub fn zip_eq<Z>(
622 self,
623 other: Z,
624 ) -> CondIterator<ri::ZipEq<P, Z::Iter>, it::ZipEq<S, Z::IntoIter>>
625 where
626 Z: IntoParallelIterator + IntoIterator<Item = <Z as IntoParallelIterator>::Item>,
627 Z::Iter: IndexedParallelIterator,
628 {
629 wrap_either!(self, iter => iter.zip_eq(other))
630 }
631
632 pub fn interleave<I>(
633 self,
634 other: I,
635 ) -> CondIterator<ri::Interleave<P, I::Iter>, it::Interleave<S, I::IntoIter>>
636 where
637 I: IntoParallelIterator<Item = P::Item> + IntoIterator<Item = S::Item>,
638 I::Iter: IndexedParallelIterator<Item = P::Item>,
639 {
640 wrap_either!(self, iter => iter.interleave(other))
641 }
642
643 pub fn interleave_shortest<I>(
644 self,
645 other: I,
646 ) -> CondIterator<ri::InterleaveShortest<P, I::Iter>, it::InterleaveShortest<S, I::IntoIter>>
647 where
648 I: IntoParallelIterator<Item = P::Item> + IntoIterator<Item = S::Item>,
649 I::Iter: IndexedParallelIterator<Item = P::Item>,
650 {
651 wrap_either!(self, iter => iter.interleave_shortest(other))
652 }
653
654 pub fn cmp<I>(self, other: I) -> Ordering
655 where
656 I: IntoParallelIterator<Item = P::Item> + IntoIterator<Item = S::Item>,
657 I::Iter: IndexedParallelIterator,
658 P::Item: Ord,
659 {
660 either!(self, iter => iter.cmp(other))
661 }
662
663 pub fn partial_cmp<I>(self, other: I) -> Option<Ordering>
664 where
665 I: IntoParallelIterator + IntoIterator<Item = <I as IntoParallelIterator>::Item>,
666 I::Iter: IndexedParallelIterator,
667 P::Item: PartialOrd<<I as IntoParallelIterator>::Item>,
668 {
669 either!(self, iter => iter.partial_cmp(other))
670 }
671
672 pub fn eq<I>(self, other: I) -> bool
673 where
674 I: IntoParallelIterator + IntoIterator<Item = <I as IntoParallelIterator>::Item>,
675 I::Iter: IndexedParallelIterator,
676 P::Item: PartialEq<<I as IntoParallelIterator>::Item>,
677 {
678 either!(self, iter => iter.eq(other))
679 }
680
681 pub fn ne<I>(self, other: I) -> bool
682 where
683 I: IntoParallelIterator + IntoIterator<Item = <I as IntoParallelIterator>::Item>,
684 I::Iter: IndexedParallelIterator,
685 P::Item: PartialEq<<I as IntoParallelIterator>::Item>,
686 {
687 either!(self, iter => iter.ne(other))
688 }
689
690 pub fn lt<I>(self, other: I) -> bool
691 where
692 I: IntoParallelIterator + IntoIterator<Item = <I as IntoParallelIterator>::Item>,
693 I::Iter: IndexedParallelIterator,
694 P::Item: PartialOrd<<I as IntoParallelIterator>::Item>,
695 {
696 either!(self, iter => iter.lt(other))
697 }
698
699 pub fn le<I>(self, other: I) -> bool
700 where
701 I: IntoParallelIterator + IntoIterator<Item = <I as IntoParallelIterator>::Item>,
702 I::Iter: IndexedParallelIterator,
703 P::Item: PartialOrd<<I as IntoParallelIterator>::Item>,
704 {
705 either!(self, iter => iter.le(other))
706 }
707
708 pub fn gt<I>(self, other: I) -> bool
709 where
710 I: IntoParallelIterator + IntoIterator<Item = <I as IntoParallelIterator>::Item>,
711 I::Iter: IndexedParallelIterator,
712 P::Item: PartialOrd<<I as IntoParallelIterator>::Item>,
713 {
714 either!(self, iter => iter.gt(other))
715 }
716
717 pub fn ge<I>(self, other: I) -> bool
718 where
719 I: IntoParallelIterator + IntoIterator<Item = <I as IntoParallelIterator>::Item>,
720 I::Iter: IndexedParallelIterator,
721 P::Item: PartialOrd<<I as IntoParallelIterator>::Item>,
722 {
723 either!(self, iter => iter.ge(other))
724 }
725
726 pub fn enumerate(self) -> CondIterator<ri::Enumerate<P>, si::Enumerate<S>> {
727 wrap_either!(self, iter => iter.enumerate())
728 }
729
730 pub fn skip(self, n: usize) -> CondIterator<ri::Skip<P>, si::Skip<S>> {
731 wrap_either!(self, iter => iter.skip(n))
732 }
733
734 pub fn take(self, n: usize) -> CondIterator<ri::Take<P>, si::Take<S>> {
735 wrap_either!(self, iter => iter.take(n))
736 }
737
738 pub fn position_any<Pred>(self, predicate: Pred) -> Option<usize>
739 where
740 Pred: Fn(P::Item) -> bool + Sync + Send,
741 {
742 match self {
743 Parallel(iter) => iter.position_any(predicate),
744 Serial(mut iter) => iter.position(predicate),
745 }
746 }
747
748 pub fn position_first<Pred>(self, predicate: Pred) -> Option<usize>
749 where
750 Pred: Fn(P::Item) -> bool + Sync + Send,
751 {
752 match self {
753 Parallel(iter) => iter.position_first(predicate),
754 Serial(mut iter) => iter.position(predicate),
755 }
756 }
757
758 pub fn positions<Pred>(
759 self,
760 predicate: Pred,
761 ) -> CondIterator<ri::Positions<P, Pred>, it::Positions<S, Pred>>
762 where
763 Pred: Fn(P::Item) -> bool + Sync + Send,
764 {
765 wrap_either!(self, iter => iter.positions(predicate))
766 }
767
768 pub fn step_by(self, step: usize) -> CondIterator<ri::StepBy<P>, si::StepBy<S>> {
769 wrap_either!(self, iter => iter.step_by(step))
770 }
771}
772
773impl<P, S> CondIterator<P, S>
774where
775 P: IndexedParallelIterator,
776 S: DoubleEndedIterator<Item = P::Item>,
777{
778 pub fn rev(self) -> CondIterator<ri::Rev<P>, si::Rev<S>> {
779 wrap_either!(self, iter => iter.rev())
780 }
781}
782
783impl<P, S> CondIterator<P, S>
784where
785 P: IndexedParallelIterator,
786 S: ExactSizeIterator<Item = P::Item>,
787{
788 #[allow(clippy::len_without_is_empty)]
789 pub fn len(&self) -> usize {
790 either!(self, ref iter => iter.len())
791 }
792}
793
794impl<P, S> CondIterator<P, S>
795where
796 P: IndexedParallelIterator,
797 S: ExactSizeIterator + DoubleEndedIterator<Item = P::Item>,
798{
799 pub fn position_last<Pred>(self, predicate: Pred) -> Option<usize>
800 where
801 Pred: Fn(P::Item) -> bool + Sync + Send,
802 {
803 match self {
804 Parallel(iter) => iter.position_last(predicate),
805 Serial(mut iter) => iter.rposition(predicate),
806 }
807 }
808}
809
810pub trait FromCondIterator<T>: FromParallelIterator<T> + si::FromIterator<T>
811where
812 T: Send,
813{
814 fn from_cond_iter<P, S>(cond_iter: CondIterator<P, S>) -> Self
815 where
816 P: ParallelIterator<Item = T>,
817 S: Iterator<Item = T>,
818 {
819 match cond_iter {
820 Parallel(iter) => Self::from_par_iter(iter),
821 Serial(iter) => Self::from_iter(iter),
822 }
823 }
824}
825
826impl<C, T> FromCondIterator<T> for C
827where
828 C: FromParallelIterator<T> + si::FromIterator<T>,
829 T: Send,
830{
831}
832
833pub trait CondExtend<T>: ParallelExtend<T> + Extend<T>
834where
835 T: Send,
836{
837 fn cond_extend<P, S>(&mut self, cond_iter: CondIterator<P, S>)
838 where
839 P: ParallelIterator<Item = T>,
840 S: Iterator<Item = T>,
841 {
842 match cond_iter {
843 Parallel(iter) => self.par_extend(iter),
844 Serial(iter) => self.extend(iter),
845 }
846 }
847}
848
849impl<C, T> CondExtend<T> for C
850where
851 C: ParallelExtend<T> + Extend<T>,
852 T: Send,
853{
854}