itertools/
put_back_n_impl.rs

1use size_hint;
2
3/// An iterator adaptor that allows putting multiple
4/// items in front of the iterator.
5///
6/// Iterator element type is `I::Item`.
7#[derive(Debug, Clone)]
8pub struct PutBackN<I: Iterator> {
9    top: Vec<I::Item>,
10    iter: I,
11}
12
13/// Create an iterator where you can put back multiple values to the front
14/// of the iteration.
15///
16/// Iterator element type is `I::Item`.
17pub fn put_back_n<I>(iterable: I) -> PutBackN<I::IntoIter>
18    where I: IntoIterator
19{
20    PutBackN {
21        top: Vec::new(),
22        iter: iterable.into_iter(),
23    }
24}
25
26impl<I: Iterator> PutBackN<I> {
27    /// Puts x in front of the iterator.
28    /// The values are yielded in order of the most recently put back
29    /// values first.
30    ///
31    /// ```rust
32    /// use itertools::put_back_n;
33    ///
34    /// let mut it = put_back_n(1..5);
35    /// it.next();
36    /// it.put_back(1);
37    /// it.put_back(0);
38    ///
39    /// assert!(itertools::equal(it, 0..5));
40    /// ```
41    #[inline]
42    pub fn put_back(&mut self, x: I::Item) {
43        self.top.push(x);
44    }
45}
46
47impl<I: Iterator> Iterator for PutBackN<I> {
48    type Item = I::Item;
49    #[inline]
50    fn next(&mut self) -> Option<I::Item> {
51        if self.top.is_empty() {
52            self.iter.next()
53        } else {
54            self.top.pop()
55        }
56    }
57
58    #[inline]
59    fn size_hint(&self) -> (usize, Option<usize>) {
60        size_hint::add_scalar(self.iter.size_hint(), self.top.len())
61    }
62}
63