1use std::{
2 cell::Cell,
3 iter::{self, Fuse},
4};
5
6use super::{plumbing::*, *};
7
8#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
15#[derive(Clone, Debug)]
16pub struct Intersperse<I>
17where
18 I: ParallelIterator,
19 I::Item: Clone,
20{
21 base: I,
22 item: I::Item,
23}
24
25impl<I> Intersperse<I>
26where
27 I: ParallelIterator,
28 I::Item: Clone,
29{
30 pub(super) fn new(base: I, item: I::Item) -> Self {
32 Intersperse { base, item }
33 }
34}
35
36impl<I> ParallelIterator for Intersperse<I>
37where
38 I: ParallelIterator,
39 I::Item: Clone + Send,
40{
41 type Item = I::Item;
42
43 fn drive_unindexed<C>(self, consumer: C) -> C::Result
44 where
45 C: UnindexedConsumer<I::Item>,
46 {
47 let consumer1 = IntersperseConsumer::new(consumer, self.item);
48 self.base.drive_unindexed(consumer1)
49 }
50
51 fn opt_len(&self) -> Option<usize> {
52 match self.base.opt_len()? {
53 0 => Some(0),
54 len => len.checked_add(len - 1),
55 }
56 }
57}
58
59impl<I> IndexedParallelIterator for Intersperse<I>
60where
61 I: IndexedParallelIterator,
62 I::Item: Clone + Send,
63{
64 fn drive<C>(self, consumer: C) -> C::Result
65 where
66 C: Consumer<Self::Item>,
67 {
68 let consumer1 = IntersperseConsumer::new(consumer, self.item);
69 self.base.drive(consumer1)
70 }
71
72 fn len(&self) -> usize {
73 let len = self.base.len();
74 if len > 0 {
75 len.checked_add(len - 1).expect("overflow")
76 } else {
77 0
78 }
79 }
80
81 fn with_producer<CB>(self, callback: CB) -> CB::Output
82 where
83 CB: ProducerCallback<Self::Item>,
84 {
85 let len = self.len();
86 return self.base.with_producer(Callback {
87 callback,
88 item: self.item,
89 len,
90 });
91
92 struct Callback<CB, T> {
93 callback: CB,
94 item: T,
95 len: usize,
96 }
97
98 impl<T, CB> ProducerCallback<T> for Callback<CB, T>
99 where
100 CB: ProducerCallback<T>,
101 T: Clone + Send,
102 {
103 type Output = CB::Output;
104
105 fn callback<P>(self, base: P) -> CB::Output
106 where
107 P: Producer<Item = T>,
108 {
109 let producer = IntersperseProducer::new(base, self.item, self.len);
110 self.callback.callback(producer)
111 }
112 }
113 }
114}
115
116struct IntersperseProducer<P>
117where
118 P: Producer,
119{
120 base: P,
121 item: P::Item,
122 len: usize,
123 clone_first: bool,
124}
125
126impl<P> IntersperseProducer<P>
127where
128 P: Producer,
129{
130 fn new(base: P, item: P::Item, len: usize) -> Self {
131 IntersperseProducer {
132 base,
133 item,
134 len,
135 clone_first: false,
136 }
137 }
138}
139
140impl<P> Producer for IntersperseProducer<P>
141where
142 P: Producer,
143 P::Item: Clone + Send,
144{
145 type IntoIter = IntersperseIter<P::IntoIter>;
146 type Item = P::Item;
147
148 fn into_iter(self) -> Self::IntoIter {
149 IntersperseIter {
150 base: self.base.into_iter().fuse(),
151 item: self.item,
152 clone_first: self.len > 0 && self.clone_first,
153
154 clone_last: self.len > 1 && ((self.len & 1 == 0) ^ self.clone_first),
157 }
158 }
159
160 fn min_len(&self) -> usize {
161 self.base.min_len()
162 }
163
164 fn max_len(&self) -> usize {
165 self.base.max_len()
166 }
167
168 fn split_at(self, index: usize) -> (Self, Self) {
169 debug_assert!(index <= self.len);
170
171 let base_index = (index + !self.clone_first as usize) / 2;
176 let (left_base, right_base) = self.base.split_at(base_index);
177
178 let left = IntersperseProducer {
179 base: left_base,
180 item: self.item.clone(),
181 len: index,
182 clone_first: self.clone_first,
183 };
184
185 let right = IntersperseProducer {
186 base: right_base,
187 item: self.item,
188 len: self.len - index,
189
190 clone_first: (index & 1 == 1) ^ self.clone_first,
192 };
193
194 (left, right)
195 }
196
197 fn fold_with<F>(self, folder: F) -> F
198 where
199 F: Folder<Self::Item>,
200 {
201 let folder1 = IntersperseFolder {
202 base: folder,
203 item: self.item,
204 clone_first: self.clone_first,
205 };
206 self.base.fold_with(folder1).base
207 }
208}
209
210struct IntersperseIter<I>
211where
212 I: Iterator,
213{
214 base: Fuse<I>,
215 item: I::Item,
216 clone_first: bool,
217 clone_last: bool,
218}
219
220impl<I> Iterator for IntersperseIter<I>
221where
222 I: DoubleEndedIterator + ExactSizeIterator,
223 I::Item: Clone,
224{
225 type Item = I::Item;
226
227 fn next(&mut self) -> Option<Self::Item> {
228 if self.clone_first {
229 self.clone_first = false;
230 Some(self.item.clone())
231 } else if let next @ Some(_) = self.base.next() {
232 self.clone_first = self.base.len() != 0;
234 next
235 } else if self.clone_last {
236 self.clone_last = false;
237 Some(self.item.clone())
238 } else {
239 None
240 }
241 }
242
243 fn size_hint(&self) -> (usize, Option<usize>) {
244 let len = self.len();
245 (len, Some(len))
246 }
247}
248
249impl<I> DoubleEndedIterator for IntersperseIter<I>
250where
251 I: DoubleEndedIterator + ExactSizeIterator,
252 I::Item: Clone,
253{
254 fn next_back(&mut self) -> Option<Self::Item> {
255 if self.clone_last {
256 self.clone_last = false;
257 Some(self.item.clone())
258 } else if let next_back @ Some(_) = self.base.next_back() {
259 self.clone_last = self.base.len() != 0;
261 next_back
262 } else if self.clone_first {
263 self.clone_first = false;
264 Some(self.item.clone())
265 } else {
266 None
267 }
268 }
269}
270
271impl<I> ExactSizeIterator for IntersperseIter<I>
272where
273 I: DoubleEndedIterator + ExactSizeIterator,
274 I::Item: Clone,
275{
276 fn len(&self) -> usize {
277 let len = self.base.len();
278 len + len.saturating_sub(1) + self.clone_first as usize + self.clone_last as usize
279 }
280}
281
282struct IntersperseConsumer<C, T> {
283 base: C,
284 item: T,
285 clone_first: Cell<bool>,
286}
287
288impl<C, T> IntersperseConsumer<C, T>
289where
290 C: Consumer<T>,
291{
292 fn new(base: C, item: T) -> Self {
293 IntersperseConsumer {
294 base,
295 item,
296 clone_first: false.into(),
297 }
298 }
299}
300
301impl<C, T> Consumer<T> for IntersperseConsumer<C, T>
302where
303 C: Consumer<T>,
304 T: Clone + Send,
305{
306 type Folder = IntersperseFolder<C::Folder, T>;
307 type Reducer = C::Reducer;
308 type Result = C::Result;
309
310 fn split_at(mut self, index: usize) -> (Self, Self, Self::Reducer) {
311 let base_index = index + index.saturating_sub(!self.clone_first.get() as usize);
314 let (left, right, reducer) = self.base.split_at(base_index);
315
316 let right = IntersperseConsumer {
317 base: right,
318 item: self.item.clone(),
319 clone_first: true.into(),
320 };
321 self.base = left;
322 (self, right, reducer)
323 }
324
325 fn into_folder(self) -> Self::Folder {
326 IntersperseFolder {
327 base: self.base.into_folder(),
328 item: self.item,
329 clone_first: self.clone_first.get(),
330 }
331 }
332
333 fn full(&self) -> bool {
334 self.base.full()
335 }
336}
337
338impl<C, T> UnindexedConsumer<T> for IntersperseConsumer<C, T>
339where
340 C: UnindexedConsumer<T>,
341 T: Clone + Send,
342{
343 fn split_off_left(&self) -> Self {
344 let left = IntersperseConsumer {
345 base: self.base.split_off_left(),
346 item: self.item.clone(),
347 clone_first: self.clone_first.clone(),
348 };
349 self.clone_first.set(true);
350 left
351 }
352
353 fn to_reducer(&self) -> Self::Reducer {
354 self.base.to_reducer()
355 }
356}
357
358struct IntersperseFolder<C, T> {
359 base: C,
360 item: T,
361 clone_first: bool,
362}
363
364impl<C, T> Folder<T> for IntersperseFolder<C, T>
365where
366 C: Folder<T>,
367 T: Clone,
368{
369 type Result = C::Result;
370
371 fn consume(mut self, item: T) -> Self {
372 if self.clone_first {
373 self.base = self.base.consume(self.item.clone());
374 if self.base.full() {
375 return self;
376 }
377 } else {
378 self.clone_first = true;
379 }
380 self.base = self.base.consume(item);
381 self
382 }
383
384 fn consume_iter<I>(self, iter: I) -> Self
385 where
386 I: IntoIterator<Item = T>,
387 {
388 let mut clone_first = self.clone_first;
389 let between_item = self.item;
390 let base = self.base.consume_iter(iter.into_iter().flat_map(|item| {
391 let first = if clone_first {
392 Some(between_item.clone())
393 } else {
394 clone_first = true;
395 None
396 };
397 first.into_iter().chain(iter::once(item))
398 }));
399 IntersperseFolder {
400 base,
401 item: between_item,
402 clone_first,
403 }
404 }
405
406 fn complete(self) -> C::Result {
407 self.base.complete()
408 }
409
410 fn full(&self) -> bool {
411 self.base.full()
412 }
413}