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