1 use super::plumbing::*;
2 use super::*;
3 
4 use std::fmt::{self, Debug};
5 
6 /// `FlatMapIter` maps each element to a serial iterator, then flattens these iterators together.
7 /// This struct is created by the [`flat_map_iter()`] method on [`ParallelIterator`]
8 ///
9 /// [`flat_map_iter()`]: trait.ParallelIterator.html#method.flat_map_iter
10 /// [`ParallelIterator`]: trait.ParallelIterator.html
11 #[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
12 #[derive(Clone)]
13 pub struct FlatMapIter<I: ParallelIterator, F> {
14     base: I,
15     map_op: F,
16 }
17 
18 impl<I: ParallelIterator + Debug, F> Debug for FlatMapIter<I, F> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result19     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
20         f.debug_struct("FlatMapIter")
21             .field("base", &self.base)
22             .finish()
23     }
24 }
25 
26 impl<I: ParallelIterator, F> FlatMapIter<I, F> {
27     /// Creates a new `FlatMapIter` iterator.
new(base: I, map_op: F) -> Self28     pub(super) fn new(base: I, map_op: F) -> Self {
29         FlatMapIter { base, map_op }
30     }
31 }
32 
33 impl<I, F, SI> ParallelIterator for FlatMapIter<I, F>
34 where
35     I: ParallelIterator,
36     F: Fn(I::Item) -> SI + Sync + Send,
37     SI: IntoIterator,
38     SI::Item: Send,
39 {
40     type Item = SI::Item;
41 
drive_unindexed<C>(self, consumer: C) -> C::Result where C: UnindexedConsumer<Self::Item>,42     fn drive_unindexed<C>(self, consumer: C) -> C::Result
43     where
44         C: UnindexedConsumer<Self::Item>,
45     {
46         let consumer = FlatMapIterConsumer::new(consumer, &self.map_op);
47         self.base.drive_unindexed(consumer)
48     }
49 }
50 
51 /// ////////////////////////////////////////////////////////////////////////
52 /// Consumer implementation
53 
54 struct FlatMapIterConsumer<'f, C, F> {
55     base: C,
56     map_op: &'f F,
57 }
58 
59 impl<'f, C, F> FlatMapIterConsumer<'f, C, F> {
new(base: C, map_op: &'f F) -> Self60     fn new(base: C, map_op: &'f F) -> Self {
61         FlatMapIterConsumer { base, map_op }
62     }
63 }
64 
65 impl<'f, T, U, C, F> Consumer<T> for FlatMapIterConsumer<'f, C, F>
66 where
67     C: UnindexedConsumer<U::Item>,
68     F: Fn(T) -> U + Sync,
69     U: IntoIterator,
70 {
71     type Folder = FlatMapIterFolder<'f, C::Folder, F>;
72     type Reducer = C::Reducer;
73     type Result = C::Result;
74 
split_at(self, index: usize) -> (Self, Self, C::Reducer)75     fn split_at(self, index: usize) -> (Self, Self, C::Reducer) {
76         let (left, right, reducer) = self.base.split_at(index);
77         (
78             FlatMapIterConsumer::new(left, self.map_op),
79             FlatMapIterConsumer::new(right, self.map_op),
80             reducer,
81         )
82     }
83 
into_folder(self) -> Self::Folder84     fn into_folder(self) -> Self::Folder {
85         FlatMapIterFolder {
86             base: self.base.into_folder(),
87             map_op: self.map_op,
88         }
89     }
90 
full(&self) -> bool91     fn full(&self) -> bool {
92         self.base.full()
93     }
94 }
95 
96 impl<'f, T, U, C, F> UnindexedConsumer<T> for FlatMapIterConsumer<'f, C, F>
97 where
98     C: UnindexedConsumer<U::Item>,
99     F: Fn(T) -> U + Sync,
100     U: IntoIterator,
101 {
split_off_left(&self) -> Self102     fn split_off_left(&self) -> Self {
103         FlatMapIterConsumer::new(self.base.split_off_left(), self.map_op)
104     }
105 
to_reducer(&self) -> Self::Reducer106     fn to_reducer(&self) -> Self::Reducer {
107         self.base.to_reducer()
108     }
109 }
110 
111 struct FlatMapIterFolder<'f, C, F> {
112     base: C,
113     map_op: &'f F,
114 }
115 
116 impl<'f, T, U, C, F> Folder<T> for FlatMapIterFolder<'f, C, F>
117 where
118     C: Folder<U::Item>,
119     F: Fn(T) -> U,
120     U: IntoIterator,
121 {
122     type Result = C::Result;
123 
consume(self, item: T) -> Self124     fn consume(self, item: T) -> Self {
125         let map_op = self.map_op;
126         let base = self.base.consume_iter(map_op(item));
127         FlatMapIterFolder { base, map_op }
128     }
129 
consume_iter<I>(self, iter: I) -> Self where I: IntoIterator<Item = T>,130     fn consume_iter<I>(self, iter: I) -> Self
131     where
132         I: IntoIterator<Item = T>,
133     {
134         let map_op = self.map_op;
135         let iter = iter.into_iter().flat_map(map_op);
136         let base = self.base.consume_iter(iter);
137         FlatMapIterFolder { base, map_op }
138     }
139 
complete(self) -> Self::Result140     fn complete(self) -> Self::Result {
141         self.base.complete()
142     }
143 
full(&self) -> bool144     fn full(&self) -> bool {
145         self.base.full()
146     }
147 }
148