1 | use super::plumbing::*; |
2 | use super::*; |
3 | use std::iter::Fuse; |
4 | |
5 | /// `Interleave` is an iterator that interleaves elements of iterators |
6 | /// `i` and `j` in one continuous iterator. This struct is created by |
7 | /// the [`interleave()`] method on [`IndexedParallelIterator`] |
8 | /// |
9 | /// [`interleave()`]: trait.IndexedParallelIterator.html#method.interleave |
10 | /// [`IndexedParallelIterator`]: trait.IndexedParallelIterator.html |
11 | #[must_use = "iterator adaptors are lazy and do nothing unless consumed" ] |
12 | #[derive (Debug, Clone)] |
13 | pub struct Interleave<I, J> |
14 | where |
15 | I: IndexedParallelIterator, |
16 | J: IndexedParallelIterator<Item = I::Item>, |
17 | { |
18 | i: I, |
19 | j: J, |
20 | } |
21 | |
22 | impl<I, J> Interleave<I, J> |
23 | where |
24 | I: IndexedParallelIterator, |
25 | J: IndexedParallelIterator<Item = I::Item>, |
26 | { |
27 | /// Creates a new `Interleave` iterator |
28 | pub(super) fn new(i: I, j: J) -> Self { |
29 | Interleave { i, j } |
30 | } |
31 | } |
32 | |
33 | impl<I, J> ParallelIterator for Interleave<I, J> |
34 | where |
35 | I: IndexedParallelIterator, |
36 | J: IndexedParallelIterator<Item = I::Item>, |
37 | { |
38 | type Item = I::Item; |
39 | |
40 | fn drive_unindexed<C>(self, consumer: C) -> C::Result |
41 | where |
42 | C: Consumer<I::Item>, |
43 | { |
44 | bridge(self, consumer) |
45 | } |
46 | |
47 | fn opt_len(&self) -> Option<usize> { |
48 | Some(self.len()) |
49 | } |
50 | } |
51 | |
52 | impl<I, J> IndexedParallelIterator for Interleave<I, J> |
53 | where |
54 | I: IndexedParallelIterator, |
55 | J: IndexedParallelIterator<Item = I::Item>, |
56 | { |
57 | fn drive<C>(self, consumer: C) -> C::Result |
58 | where |
59 | C: Consumer<Self::Item>, |
60 | { |
61 | bridge(self, consumer) |
62 | } |
63 | |
64 | fn len(&self) -> usize { |
65 | self.i.len().checked_add(self.j.len()).expect("overflow" ) |
66 | } |
67 | |
68 | fn with_producer<CB>(self, callback: CB) -> CB::Output |
69 | where |
70 | CB: ProducerCallback<Self::Item>, |
71 | { |
72 | let (i_len, j_len) = (self.i.len(), self.j.len()); |
73 | return self.i.with_producer(CallbackI { |
74 | callback, |
75 | i_len, |
76 | j_len, |
77 | i_next: false, |
78 | j: self.j, |
79 | }); |
80 | |
81 | struct CallbackI<CB, J> { |
82 | callback: CB, |
83 | i_len: usize, |
84 | j_len: usize, |
85 | i_next: bool, |
86 | j: J, |
87 | } |
88 | |
89 | impl<CB, J> ProducerCallback<J::Item> for CallbackI<CB, J> |
90 | where |
91 | J: IndexedParallelIterator, |
92 | CB: ProducerCallback<J::Item>, |
93 | { |
94 | type Output = CB::Output; |
95 | |
96 | fn callback<I>(self, i_producer: I) -> Self::Output |
97 | where |
98 | I: Producer<Item = J::Item>, |
99 | { |
100 | self.j.with_producer(CallbackJ { |
101 | i_producer, |
102 | i_len: self.i_len, |
103 | j_len: self.j_len, |
104 | i_next: self.i_next, |
105 | callback: self.callback, |
106 | }) |
107 | } |
108 | } |
109 | |
110 | struct CallbackJ<CB, I> { |
111 | callback: CB, |
112 | i_len: usize, |
113 | j_len: usize, |
114 | i_next: bool, |
115 | i_producer: I, |
116 | } |
117 | |
118 | impl<CB, I> ProducerCallback<I::Item> for CallbackJ<CB, I> |
119 | where |
120 | I: Producer, |
121 | CB: ProducerCallback<I::Item>, |
122 | { |
123 | type Output = CB::Output; |
124 | |
125 | fn callback<J>(self, j_producer: J) -> Self::Output |
126 | where |
127 | J: Producer<Item = I::Item>, |
128 | { |
129 | let producer = InterleaveProducer::new( |
130 | self.i_producer, |
131 | j_producer, |
132 | self.i_len, |
133 | self.j_len, |
134 | self.i_next, |
135 | ); |
136 | self.callback.callback(producer) |
137 | } |
138 | } |
139 | } |
140 | } |
141 | |
142 | struct InterleaveProducer<I, J> |
143 | where |
144 | I: Producer, |
145 | J: Producer<Item = I::Item>, |
146 | { |
147 | i: I, |
148 | j: J, |
149 | i_len: usize, |
150 | j_len: usize, |
151 | i_next: bool, |
152 | } |
153 | |
154 | impl<I, J> InterleaveProducer<I, J> |
155 | where |
156 | I: Producer, |
157 | J: Producer<Item = I::Item>, |
158 | { |
159 | fn new(i: I, j: J, i_len: usize, j_len: usize, i_next: bool) -> InterleaveProducer<I, J> { |
160 | InterleaveProducer { |
161 | i, |
162 | j, |
163 | i_len, |
164 | j_len, |
165 | i_next, |
166 | } |
167 | } |
168 | } |
169 | |
170 | impl<I, J> Producer for InterleaveProducer<I, J> |
171 | where |
172 | I: Producer, |
173 | J: Producer<Item = I::Item>, |
174 | { |
175 | type Item = I::Item; |
176 | type IntoIter = InterleaveSeq<I::IntoIter, J::IntoIter>; |
177 | |
178 | fn into_iter(self) -> Self::IntoIter { |
179 | InterleaveSeq { |
180 | i: self.i.into_iter().fuse(), |
181 | j: self.j.into_iter().fuse(), |
182 | i_next: self.i_next, |
183 | } |
184 | } |
185 | |
186 | fn min_len(&self) -> usize { |
187 | Ord::max(self.i.min_len(), self.j.min_len()) |
188 | } |
189 | |
190 | fn max_len(&self) -> usize { |
191 | Ord::min(self.i.max_len(), self.j.max_len()) |
192 | } |
193 | |
194 | /// We know 0 < index <= self.i_len + self.j_len |
195 | /// |
196 | /// Find a, b satisfying: |
197 | /// |
198 | /// (1) 0 < a <= self.i_len |
199 | /// (2) 0 < b <= self.j_len |
200 | /// (3) a + b == index |
201 | /// |
202 | /// For even splits, set a = b = index/2. |
203 | /// For odd splits, set a = (index/2)+1, b = index/2, if `i` |
204 | /// should yield the next element, otherwise, if `j` should yield |
205 | /// the next element, set a = index/2 and b = (index/2)+1 |
206 | fn split_at(self, index: usize) -> (Self, Self) { |
207 | #[inline ] |
208 | fn odd_offset(flag: bool) -> usize { |
209 | (!flag) as usize |
210 | } |
211 | |
212 | let even = index % 2 == 0; |
213 | let idx = index >> 1; |
214 | |
215 | // desired split |
216 | let (i_idx, j_idx) = ( |
217 | idx + odd_offset(even || self.i_next), |
218 | idx + odd_offset(even || !self.i_next), |
219 | ); |
220 | |
221 | let (i_split, j_split) = if self.i_len >= i_idx && self.j_len >= j_idx { |
222 | (i_idx, j_idx) |
223 | } else if self.i_len >= i_idx { |
224 | // j too short |
225 | (index - self.j_len, self.j_len) |
226 | } else { |
227 | // i too short |
228 | (self.i_len, index - self.i_len) |
229 | }; |
230 | |
231 | let trailing_i_next = even == self.i_next; |
232 | let (i_left, i_right) = self.i.split_at(i_split); |
233 | let (j_left, j_right) = self.j.split_at(j_split); |
234 | |
235 | ( |
236 | InterleaveProducer::new(i_left, j_left, i_split, j_split, self.i_next), |
237 | InterleaveProducer::new( |
238 | i_right, |
239 | j_right, |
240 | self.i_len - i_split, |
241 | self.j_len - j_split, |
242 | trailing_i_next, |
243 | ), |
244 | ) |
245 | } |
246 | } |
247 | |
248 | /// Wrapper for Interleave to implement DoubleEndedIterator and |
249 | /// ExactSizeIterator. |
250 | /// |
251 | /// This iterator is fused. |
252 | struct InterleaveSeq<I, J> { |
253 | i: Fuse<I>, |
254 | j: Fuse<J>, |
255 | |
256 | /// Flag to control which iterator should provide the next element. When |
257 | /// `false` then `i` produces the next element, otherwise `j` produces the |
258 | /// next element. |
259 | i_next: bool, |
260 | } |
261 | |
262 | /// Iterator implementation for InterleaveSeq. This implementation is |
263 | /// taken more or less verbatim from itertools. It is replicated here |
264 | /// (instead of calling itertools directly), because we also need to |
265 | /// implement `DoubledEndedIterator` and `ExactSizeIterator`. |
266 | impl<I, J> Iterator for InterleaveSeq<I, J> |
267 | where |
268 | I: Iterator, |
269 | J: Iterator<Item = I::Item>, |
270 | { |
271 | type Item = I::Item; |
272 | |
273 | #[inline ] |
274 | fn next(&mut self) -> Option<Self::Item> { |
275 | self.i_next = !self.i_next; |
276 | if self.i_next { |
277 | match self.i.next() { |
278 | None => self.j.next(), |
279 | r => r, |
280 | } |
281 | } else { |
282 | match self.j.next() { |
283 | None => self.i.next(), |
284 | r => r, |
285 | } |
286 | } |
287 | } |
288 | |
289 | fn size_hint(&self) -> (usize, Option<usize>) { |
290 | let (ih, jh) = (self.i.size_hint(), self.j.size_hint()); |
291 | let min = ih.0.saturating_add(jh.0); |
292 | let max = match (ih.1, jh.1) { |
293 | (Some(x), Some(y)) => x.checked_add(y), |
294 | _ => None, |
295 | }; |
296 | (min, max) |
297 | } |
298 | } |
299 | |
300 | // The implementation for DoubleEndedIterator requires |
301 | // ExactSizeIterator to provide `next_back()`. The last element will |
302 | // come from the iterator that runs out last (ie has the most elements |
303 | // in it). If the iterators have the same number of elements, then the |
304 | // last iterator will provide the last element. |
305 | impl<I, J> DoubleEndedIterator for InterleaveSeq<I, J> |
306 | where |
307 | I: DoubleEndedIterator + ExactSizeIterator, |
308 | J: DoubleEndedIterator<Item = I::Item> + ExactSizeIterator<Item = I::Item>, |
309 | { |
310 | #[inline ] |
311 | fn next_back(&mut self) -> Option<I::Item> { |
312 | match self.i.len().cmp(&self.j.len()) { |
313 | Ordering::Less => self.j.next_back(), |
314 | Ordering::Equal => { |
315 | if self.i_next { |
316 | self.i.next_back() |
317 | } else { |
318 | self.j.next_back() |
319 | } |
320 | } |
321 | Ordering::Greater => self.i.next_back(), |
322 | } |
323 | } |
324 | } |
325 | |
326 | impl<I, J> ExactSizeIterator for InterleaveSeq<I, J> |
327 | where |
328 | I: ExactSizeIterator, |
329 | J: ExactSizeIterator<Item = I::Item>, |
330 | { |
331 | #[inline ] |
332 | fn len(&self) -> usize { |
333 | self.i.len() + self.j.len() |
334 | } |
335 | } |
336 | |