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}
272