]>
Commit | Line | Data |
---|---|---|
2c00a5a8 XL |
1 | use super::plumbing::*; |
2 | use super::*; | |
3 | ||
4 | use std::fmt::{self, Debug}; | |
5 | use std::iter; | |
6 | ||
2c00a5a8 XL |
7 | /// `Map` is an iterator that transforms the elements of an underlying iterator. |
8 | /// | |
9 | /// This struct is created by the [`map()`] method on [`ParallelIterator`] | |
10 | /// | |
11 | /// [`map()`]: trait.ParallelIterator.html#method.map | |
12 | /// [`ParallelIterator`]: trait.ParallelIterator.html | |
13 | #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] | |
14 | #[derive(Clone)] | |
15 | pub struct Map<I: ParallelIterator, F> { | |
16 | base: I, | |
17 | map_op: F, | |
18 | } | |
19 | ||
20 | impl<I: ParallelIterator + Debug, F> Debug for Map<I, F> { | |
e74abb32 | 21 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
532ac7d7 | 22 | f.debug_struct("Map").field("base", &self.base).finish() |
2c00a5a8 XL |
23 | } |
24 | } | |
25 | ||
e74abb32 | 26 | impl<I, F> Map<I, F> |
532ac7d7 XL |
27 | where |
28 | I: ParallelIterator, | |
2c00a5a8 | 29 | { |
e74abb32 XL |
30 | /// Create a new `Map` iterator. |
31 | pub(super) fn new(base: I, map_op: F) -> Self { | |
32 | Map { base, map_op } | |
2c00a5a8 XL |
33 | } |
34 | } | |
35 | ||
36 | impl<I, F, R> ParallelIterator for Map<I, F> | |
532ac7d7 XL |
37 | where |
38 | I: ParallelIterator, | |
39 | F: Fn(I::Item) -> R + Sync + Send, | |
40 | R: Send, | |
2c00a5a8 XL |
41 | { |
42 | type Item = F::Output; | |
43 | ||
44 | fn drive_unindexed<C>(self, consumer: C) -> C::Result | |
532ac7d7 XL |
45 | where |
46 | C: UnindexedConsumer<Self::Item>, | |
2c00a5a8 XL |
47 | { |
48 | let consumer1 = MapConsumer::new(consumer, &self.map_op); | |
49 | self.base.drive_unindexed(consumer1) | |
50 | } | |
51 | ||
52 | fn opt_len(&self) -> Option<usize> { | |
53 | self.base.opt_len() | |
54 | } | |
55 | } | |
56 | ||
57 | impl<I, F, R> IndexedParallelIterator for Map<I, F> | |
532ac7d7 XL |
58 | where |
59 | I: IndexedParallelIterator, | |
60 | F: Fn(I::Item) -> R + Sync + Send, | |
61 | R: Send, | |
2c00a5a8 XL |
62 | { |
63 | fn drive<C>(self, consumer: C) -> C::Result | |
532ac7d7 XL |
64 | where |
65 | C: Consumer<Self::Item>, | |
2c00a5a8 XL |
66 | { |
67 | let consumer1 = MapConsumer::new(consumer, &self.map_op); | |
68 | self.base.drive(consumer1) | |
69 | } | |
70 | ||
71 | fn len(&self) -> usize { | |
72 | self.base.len() | |
73 | } | |
74 | ||
75 | fn with_producer<CB>(self, callback: CB) -> CB::Output | |
532ac7d7 XL |
76 | where |
77 | CB: ProducerCallback<Self::Item>, | |
2c00a5a8 XL |
78 | { |
79 | return self.base.with_producer(Callback { | |
e74abb32 | 80 | callback, |
532ac7d7 XL |
81 | map_op: self.map_op, |
82 | }); | |
2c00a5a8 XL |
83 | |
84 | struct Callback<CB, F> { | |
85 | callback: CB, | |
86 | map_op: F, | |
87 | } | |
88 | ||
89 | impl<T, F, R, CB> ProducerCallback<T> for Callback<CB, F> | |
532ac7d7 XL |
90 | where |
91 | CB: ProducerCallback<R>, | |
92 | F: Fn(T) -> R + Sync, | |
93 | R: Send, | |
2c00a5a8 XL |
94 | { |
95 | type Output = CB::Output; | |
96 | ||
97 | fn callback<P>(self, base: P) -> CB::Output | |
532ac7d7 XL |
98 | where |
99 | P: Producer<Item = T>, | |
2c00a5a8 XL |
100 | { |
101 | let producer = MapProducer { | |
e74abb32 | 102 | base, |
2c00a5a8 XL |
103 | map_op: &self.map_op, |
104 | }; | |
105 | self.callback.callback(producer) | |
106 | } | |
107 | } | |
108 | } | |
109 | } | |
110 | ||
111 | /// //////////////////////////////////////////////////////////////////////// | |
112 | ||
6a06907d | 113 | struct MapProducer<'f, P, F> { |
2c00a5a8 XL |
114 | base: P, |
115 | map_op: &'f F, | |
116 | } | |
117 | ||
118 | impl<'f, P, F, R> Producer for MapProducer<'f, P, F> | |
532ac7d7 XL |
119 | where |
120 | P: Producer, | |
121 | F: Fn(P::Item) -> R + Sync, | |
122 | R: Send, | |
2c00a5a8 XL |
123 | { |
124 | type Item = F::Output; | |
125 | type IntoIter = iter::Map<P::IntoIter, &'f F>; | |
126 | ||
127 | fn into_iter(self) -> Self::IntoIter { | |
128 | self.base.into_iter().map(self.map_op) | |
129 | } | |
130 | ||
131 | fn min_len(&self) -> usize { | |
132 | self.base.min_len() | |
133 | } | |
134 | fn max_len(&self) -> usize { | |
135 | self.base.max_len() | |
136 | } | |
137 | ||
138 | fn split_at(self, index: usize) -> (Self, Self) { | |
139 | let (left, right) = self.base.split_at(index); | |
532ac7d7 XL |
140 | ( |
141 | MapProducer { | |
142 | base: left, | |
143 | map_op: self.map_op, | |
144 | }, | |
145 | MapProducer { | |
146 | base: right, | |
147 | map_op: self.map_op, | |
148 | }, | |
149 | ) | |
2c00a5a8 XL |
150 | } |
151 | ||
152 | fn fold_with<G>(self, folder: G) -> G | |
532ac7d7 XL |
153 | where |
154 | G: Folder<Self::Item>, | |
2c00a5a8 | 155 | { |
532ac7d7 XL |
156 | let folder1 = MapFolder { |
157 | base: folder, | |
158 | map_op: self.map_op, | |
159 | }; | |
2c00a5a8 XL |
160 | self.base.fold_with(folder1).base |
161 | } | |
162 | } | |
163 | ||
2c00a5a8 XL |
164 | /// //////////////////////////////////////////////////////////////////////// |
165 | /// Consumer implementation | |
166 | ||
6a06907d | 167 | struct MapConsumer<'f, C, F> { |
2c00a5a8 XL |
168 | base: C, |
169 | map_op: &'f F, | |
170 | } | |
171 | ||
172 | impl<'f, C, F> MapConsumer<'f, C, F> { | |
173 | fn new(base: C, map_op: &'f F) -> Self { | |
e74abb32 | 174 | MapConsumer { base, map_op } |
2c00a5a8 XL |
175 | } |
176 | } | |
177 | ||
178 | impl<'f, T, R, C, F> Consumer<T> for MapConsumer<'f, C, F> | |
532ac7d7 XL |
179 | where |
180 | C: Consumer<F::Output>, | |
181 | F: Fn(T) -> R + Sync, | |
182 | R: Send, | |
2c00a5a8 XL |
183 | { |
184 | type Folder = MapFolder<'f, C::Folder, F>; | |
185 | type Reducer = C::Reducer; | |
186 | type Result = C::Result; | |
187 | ||
188 | fn split_at(self, index: usize) -> (Self, Self, Self::Reducer) { | |
189 | let (left, right, reducer) = self.base.split_at(index); | |
532ac7d7 XL |
190 | ( |
191 | MapConsumer::new(left, self.map_op), | |
192 | MapConsumer::new(right, self.map_op), | |
193 | reducer, | |
194 | ) | |
2c00a5a8 XL |
195 | } |
196 | ||
197 | fn into_folder(self) -> Self::Folder { | |
198 | MapFolder { | |
199 | base: self.base.into_folder(), | |
200 | map_op: self.map_op, | |
201 | } | |
202 | } | |
203 | ||
204 | fn full(&self) -> bool { | |
205 | self.base.full() | |
206 | } | |
207 | } | |
208 | ||
209 | impl<'f, T, R, C, F> UnindexedConsumer<T> for MapConsumer<'f, C, F> | |
532ac7d7 XL |
210 | where |
211 | C: UnindexedConsumer<F::Output>, | |
212 | F: Fn(T) -> R + Sync, | |
213 | R: Send, | |
2c00a5a8 XL |
214 | { |
215 | fn split_off_left(&self) -> Self { | |
216 | MapConsumer::new(self.base.split_off_left(), &self.map_op) | |
217 | } | |
218 | ||
219 | fn to_reducer(&self) -> Self::Reducer { | |
220 | self.base.to_reducer() | |
221 | } | |
222 | } | |
223 | ||
6a06907d | 224 | struct MapFolder<'f, C, F> { |
2c00a5a8 XL |
225 | base: C, |
226 | map_op: &'f F, | |
227 | } | |
228 | ||
229 | impl<'f, T, R, C, F> Folder<T> for MapFolder<'f, C, F> | |
532ac7d7 XL |
230 | where |
231 | C: Folder<F::Output>, | |
232 | F: Fn(T) -> R, | |
2c00a5a8 XL |
233 | { |
234 | type Result = C::Result; | |
235 | ||
236 | fn consume(self, item: T) -> Self { | |
237 | let mapped_item = (self.map_op)(item); | |
238 | MapFolder { | |
239 | base: self.base.consume(mapped_item), | |
240 | map_op: self.map_op, | |
241 | } | |
242 | } | |
243 | ||
e74abb32 XL |
244 | fn consume_iter<I>(mut self, iter: I) -> Self |
245 | where | |
246 | I: IntoIterator<Item = T>, | |
247 | { | |
248 | self.base = self.base.consume_iter(iter.into_iter().map(self.map_op)); | |
249 | self | |
250 | } | |
251 | ||
2c00a5a8 XL |
252 | fn complete(self) -> C::Result { |
253 | self.base.complete() | |
254 | } | |
255 | ||
256 | fn full(&self) -> bool { | |
257 | self.base.full() | |
258 | } | |
259 | } |