itertools/
intersperse.rs

1use 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: 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}