par_iter/iter/
map.rs

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