1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
use std::mem::replace;

/**
(<em>a</em><sub>0</sub>, <em>a</em><sub>1</sub>, ..., <em>a</em><sub>n</sub>), <em>i</em>
&nbsp;&rarr;&nbsp;
(<em>a</em><sub>0</sub>, <em>i</em>, <em>a</em><sub>1</sub>, <em>i</em>, ..., <em>i</em>, <em>a</em><sub>n</sub>)

*/
pub trait IntersperseIterator<E>: Iterator<Item=E> + Sized {
    /**
Creates an iterator that yields `inject` between each element of the input iterator.  `inject` will not appear as the first or last element of the resulting iterator.
    */
    fn intersperse(self, inject: E) -> Intersperse<Self, E>;
}

impl<It, E> IntersperseIterator<E> for It where It: Iterator<Item=E> {
    fn intersperse(mut self, inject: E) -> Intersperse<It, E> {
        let look_ahead = self.next();
        Intersperse {
            iter: self,
            look_ahead: look_ahead,
            inject: inject,
            next_is_inject: false,
        }
    }
}

#[derive(Clone, Debug)]
pub struct Intersperse<It, E> {
    iter: It,
    look_ahead: Option<E>,
    inject: E,
    next_is_inject: bool,
}

impl<It, E> Iterator for Intersperse<It, E> where It: Iterator<Item=E>, E: Clone {
    type Item = E;

    fn next(&mut self) -> Option<E> {
        match self.next_is_inject {
            false => match replace(&mut self.look_ahead, None) {
                None => None,
                Some(e) => {
                    self.look_ahead = self.iter.next();
                    self.next_is_inject = true;
                    Some(e)
                }
            },
            true => match self.look_ahead.is_some() {
                true => {
                    self.next_is_inject = false;
                    Some(self.inject.clone())
                },
                false => {
                    None
                }
            }
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let (li, mui) = self.iter.size_hint();
        let l = match li {
            0 => 0,
            n => n + n - 1
        };
        let mu = match mui {
            Some(0) => Some(0),
            Some(n) => Some(n + n - 1),
            None => None
        };
        (l, mu)
    }
}

#[test]
fn test_intersperse() {
    let v: Vec<&str> = vec![];
    let r: Vec<_> = v.into_iter().intersperse(",").collect();
    assert_eq!(r, Vec::<&str>::new());

    let v = vec!["a"];
    let r: Vec<_> = v.into_iter().intersperse(",").collect();
    assert_eq!(r, vec!["a"]);

    let v = vec!["a", "b"];
    let r: Vec<_> = v.into_iter().intersperse(",").collect();
    assert_eq!(r, vec!["a", ",", "b"]);

    let v = vec!["a", "b", "c"];
    let r: Vec<_> = v.into_iter().intersperse(",").collect();
    assert_eq!(r, vec!["a", ",", "b", ",", "c"]);
}