blob: 0579299278496e80efe154751f596c30d3319454 [file] [log] [blame]
Jakub Kotura425e552020-12-21 17:28:15 +01001use std::iter::Fuse;
2use super::size_hint;
3
4#[derive(Clone)]
5/// An iterator adaptor to insert a particular value
6/// between each element of the adapted iterator.
7///
8/// Iterator element type is `I::Item`
9///
10/// This iterator is *fused*.
11///
12/// See [`.intersperse()`](../trait.Itertools.html#method.intersperse) for more information.
13#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
14#[derive(Debug)]
15pub struct Intersperse<I>
16 where I: Iterator
17{
18 element: I::Item,
19 iter: Fuse<I>,
20 peek: Option<I::Item>,
21}
22
23/// Create a new Intersperse iterator
24pub fn intersperse<I>(iter: I, elt: I::Item) -> Intersperse<I>
25 where I: Iterator
26{
27 let mut iter = iter.fuse();
28 Intersperse {
29 peek: iter.next(),
30 iter,
31 element: elt,
32 }
33}
34
35impl<I> Iterator for Intersperse<I>
36 where I: Iterator,
37 I::Item: Clone
38{
39 type Item = I::Item;
40 #[inline]
41 fn next(&mut self) -> Option<I::Item> {
42 if self.peek.is_some() {
43 self.peek.take()
44 } else {
45 self.peek = self.iter.next();
46 if self.peek.is_some() {
47 Some(self.element.clone())
48 } else {
49 None
50 }
51 }
52 }
53
54 fn size_hint(&self) -> (usize, Option<usize>) {
55 // 2 * SH + { 1 or 0 }
56 let has_peek = self.peek.is_some() as usize;
57 let sh = self.iter.size_hint();
58 size_hint::add_scalar(size_hint::add(sh, sh), has_peek)
59 }
60
61 fn fold<B, F>(mut self, init: B, mut f: F) -> B where
62 Self: Sized, F: FnMut(B, Self::Item) -> B,
63 {
64 let mut accum = init;
65
66 if let Some(x) = self.peek.take() {
67 accum = f(accum, x);
68 }
69
70 let element = &self.element;
71
72 self.iter.fold(accum,
73 |accum, x| {
74 let accum = f(accum, element.clone());
75 let accum = f(accum, x);
76 accum
77 })
78 }
79}