itertools/
put_back_n_impl.rs

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