rayon/iter/
len.rs

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