1 use super::plumbing::*; 2 use super::*; 3 4 /// `FlattenIter` turns each element to a serial iterator, then flattens these iterators 5 /// together. This struct is created by the [`flatten_iter()`] method on [`ParallelIterator`]. 6 /// 7 /// [`flatten_iter()`]: trait.ParallelIterator.html#method.flatten_iter 8 /// [`ParallelIterator`]: trait.ParallelIterator.html 9 #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] 10 #[derive(Debug, Clone)] 11 pub struct FlattenIter<I: ParallelIterator> { 12 base: I, 13 } 14 15 impl<I> FlattenIter<I> 16 where 17 I: ParallelIterator, 18 I::Item: IntoIterator, 19 <I::Item as IntoIterator>::Item: Send, 20 { 21 /// Creates a new `FlattenIter` iterator. new(base: I) -> Self22 pub(super) fn new(base: I) -> Self { 23 FlattenIter { base } 24 } 25 } 26 27 impl<I> ParallelIterator for FlattenIter<I> 28 where 29 I: ParallelIterator, 30 I::Item: IntoIterator, 31 <I::Item as IntoIterator>::Item: Send, 32 { 33 type Item = <I::Item as IntoIterator>::Item; 34 drive_unindexed<C>(self, consumer: C) -> C::Result where C: UnindexedConsumer<Self::Item>,35 fn drive_unindexed<C>(self, consumer: C) -> C::Result 36 where 37 C: UnindexedConsumer<Self::Item>, 38 { 39 let consumer = FlattenIterConsumer::new(consumer); 40 self.base.drive_unindexed(consumer) 41 } 42 } 43 44 /// //////////////////////////////////////////////////////////////////////// 45 /// Consumer implementation 46 47 struct FlattenIterConsumer<C> { 48 base: C, 49 } 50 51 impl<C> FlattenIterConsumer<C> { new(base: C) -> Self52 fn new(base: C) -> Self { 53 FlattenIterConsumer { base } 54 } 55 } 56 57 impl<T, C> Consumer<T> for FlattenIterConsumer<C> 58 where 59 C: UnindexedConsumer<T::Item>, 60 T: IntoIterator, 61 { 62 type Folder = FlattenIterFolder<C::Folder>; 63 type Reducer = C::Reducer; 64 type Result = C::Result; 65 split_at(self, index: usize) -> (Self, Self, C::Reducer)66 fn split_at(self, index: usize) -> (Self, Self, C::Reducer) { 67 let (left, right, reducer) = self.base.split_at(index); 68 ( 69 FlattenIterConsumer::new(left), 70 FlattenIterConsumer::new(right), 71 reducer, 72 ) 73 } 74 into_folder(self) -> Self::Folder75 fn into_folder(self) -> Self::Folder { 76 FlattenIterFolder { 77 base: self.base.into_folder(), 78 } 79 } 80 full(&self) -> bool81 fn full(&self) -> bool { 82 self.base.full() 83 } 84 } 85 86 impl<T, C> UnindexedConsumer<T> for FlattenIterConsumer<C> 87 where 88 C: UnindexedConsumer<T::Item>, 89 T: IntoIterator, 90 { split_off_left(&self) -> Self91 fn split_off_left(&self) -> Self { 92 FlattenIterConsumer::new(self.base.split_off_left()) 93 } 94 to_reducer(&self) -> Self::Reducer95 fn to_reducer(&self) -> Self::Reducer { 96 self.base.to_reducer() 97 } 98 } 99 100 struct FlattenIterFolder<C> { 101 base: C, 102 } 103 104 impl<T, C> Folder<T> for FlattenIterFolder<C> 105 where 106 C: Folder<T::Item>, 107 T: IntoIterator, 108 { 109 type Result = C::Result; 110 consume(self, item: T) -> Self111 fn consume(self, item: T) -> Self { 112 let base = self.base.consume_iter(item); 113 FlattenIterFolder { base } 114 } 115 consume_iter<I>(self, iter: I) -> Self where I: IntoIterator<Item = T>,116 fn consume_iter<I>(self, iter: I) -> Self 117 where 118 I: IntoIterator<Item = T>, 119 { 120 let iter = iter.into_iter().flatten(); 121 let base = self.base.consume_iter(iter); 122 FlattenIterFolder { base } 123 } 124 complete(self) -> Self::Result125 fn complete(self) -> Self::Result { 126 self.base.complete() 127 } 128 full(&self) -> bool129 fn full(&self) -> bool { 130 self.base.full() 131 } 132 } 133