1 use super::plumbing::*;
2 use super::*;
3 use 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)]
12 pub struct MinLen<I: IndexedParallelIterator> {
13     base: I,
14     min: usize,
15 }
16 
17 impl<I> MinLen<I>
18 where
19     I: IndexedParallelIterator,
20 {
21     /// Creates a new `MinLen` iterator.
new(base: I, min: usize) -> Self22     pub(super) fn new(base: I, min: usize) -> Self {
23         MinLen { base, min }
24     }
25 }
26 
27 impl<I> ParallelIterator for MinLen<I>
28 where
29     I: IndexedParallelIterator,
30 {
31     type Item = I::Item;
32 
drive_unindexed<C>(self, consumer: C) -> C::Result where C: UnindexedConsumer<Self::Item>,33     fn drive_unindexed<C>(self, consumer: C) -> C::Result
34     where
35         C: UnindexedConsumer<Self::Item>,
36     {
37         bridge(self, consumer)
38     }
39 
opt_len(&self) -> Option<usize>40     fn opt_len(&self) -> Option<usize> {
41         Some(self.len())
42     }
43 }
44 
45 impl<I> IndexedParallelIterator for MinLen<I>
46 where
47     I: IndexedParallelIterator,
48 {
drive<C: Consumer<Self::Item>>(self, consumer: C) -> C::Result49     fn drive<C: Consumer<Self::Item>>(self, consumer: C) -> C::Result {
50         bridge(self, consumer)
51     }
52 
len(&self) -> usize53     fn len(&self) -> usize {
54         self.base.len()
55     }
56 
with_producer<CB>(self, callback: CB) -> CB::Output where CB: ProducerCallback<Self::Item>,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 
93 struct MinLenProducer<P> {
94     base: P,
95     min: usize,
96 }
97 
98 impl<P> Producer for MinLenProducer<P>
99 where
100     P: Producer,
101 {
102     type Item = P::Item;
103     type IntoIter = P::IntoIter;
104 
into_iter(self) -> Self::IntoIter105     fn into_iter(self) -> Self::IntoIter {
106         self.base.into_iter()
107     }
108 
min_len(&self) -> usize109     fn min_len(&self) -> usize {
110         cmp::max(self.min, self.base.min_len())
111     }
112 
max_len(&self) -> usize113     fn max_len(&self) -> usize {
114         self.base.max_len()
115     }
116 
split_at(self, index: usize) -> (Self, Self)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 
fold_with<F>(self, folder: F) -> F where F: Folder<Self::Item>,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)]
146 pub struct MaxLen<I: IndexedParallelIterator> {
147     base: I,
148     max: usize,
149 }
150 
151 impl<I> MaxLen<I>
152 where
153     I: IndexedParallelIterator,
154 {
155     /// Creates a new `MaxLen` iterator.
new(base: I, max: usize) -> Self156     pub(super) fn new(base: I, max: usize) -> Self {
157         MaxLen { base, max }
158     }
159 }
160 
161 impl<I> ParallelIterator for MaxLen<I>
162 where
163     I: IndexedParallelIterator,
164 {
165     type Item = I::Item;
166 
drive_unindexed<C>(self, consumer: C) -> C::Result where C: UnindexedConsumer<Self::Item>,167     fn drive_unindexed<C>(self, consumer: C) -> C::Result
168     where
169         C: UnindexedConsumer<Self::Item>,
170     {
171         bridge(self, consumer)
172     }
173 
opt_len(&self) -> Option<usize>174     fn opt_len(&self) -> Option<usize> {
175         Some(self.len())
176     }
177 }
178 
179 impl<I> IndexedParallelIterator for MaxLen<I>
180 where
181     I: IndexedParallelIterator,
182 {
drive<C: Consumer<Self::Item>>(self, consumer: C) -> C::Result183     fn drive<C: Consumer<Self::Item>>(self, consumer: C) -> C::Result {
184         bridge(self, consumer)
185     }
186 
len(&self) -> usize187     fn len(&self) -> usize {
188         self.base.len()
189     }
190 
with_producer<CB>(self, callback: CB) -> CB::Output where CB: ProducerCallback<Self::Item>,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 
227 struct MaxLenProducer<P> {
228     base: P,
229     max: usize,
230 }
231 
232 impl<P> Producer for MaxLenProducer<P>
233 where
234     P: Producer,
235 {
236     type Item = P::Item;
237     type IntoIter = P::IntoIter;
238 
into_iter(self) -> Self::IntoIter239     fn into_iter(self) -> Self::IntoIter {
240         self.base.into_iter()
241     }
242 
min_len(&self) -> usize243     fn min_len(&self) -> usize {
244         self.base.min_len()
245     }
246 
max_len(&self) -> usize247     fn max_len(&self) -> usize {
248         cmp::min(self.max, self.base.max_len())
249     }
250 
split_at(self, index: usize) -> (Self, Self)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 
fold_with<F>(self, folder: F) -> F where F: Folder<Self::Item>,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 }
272