Skip to main content

fso_graph/
utils.rs

1#[derive(Clone, Debug)]
2/// An iterator adaptor that allows putting back a single
3/// item to the front of the iterator.
4///
5/// Iterator element type is `I::Item`.
6///
7/// Code is copied from [itertools](https://docs.rs/itertools/latest/itertools/structs/struct.PutBack.html).
8pub struct PutBack<I>
9where
10    I: Iterator,
11{
12    top: Option<I::Item>,
13    iter: I,
14}
15
16pub fn put_back_iterator<I>(iterable: I) -> PutBack<I::IntoIter>
17where
18    I: IntoIterator,
19{
20    PutBack {
21        top: None,
22        iter: iterable.into_iter(),
23    }
24}
25impl<I> PutBack<I>
26where
27    I: Iterator,
28{
29    /// Put back a single value to the front of the iterator.
30    ///
31    /// If a value is already in the put back slot, it is overwritten.
32    #[inline]
33    pub fn put_back(&mut self, x: I::Item) {
34        self.top = Some(x)
35    }
36}
37
38impl<I> Iterator for PutBack<I>
39where
40    I: Iterator,
41{
42    type Item = I::Item;
43    #[inline]
44    fn next(&mut self) -> Option<Self::Item> {
45        match self.top {
46            None => self.iter.next(),
47            ref mut some => some.take(),
48        }
49    }
50    #[inline]
51    fn size_hint(&self) -> (usize, Option<usize>) {
52        let x = usize::from(self.top.is_some());
53        let (low, hi) = self.iter.size_hint();
54        (low + x, hi.map(|e| e + x))
55    }
56
57    fn count(self) -> usize {
58        self.iter.count() + (self.top.is_some() as usize)
59    }
60
61    fn last(self) -> Option<Self::Item> {
62        self.iter.last().or(self.top)
63    }
64
65    fn nth(&mut self, n: usize) -> Option<Self::Item> {
66        match self.top {
67            None => self.iter.nth(n),
68            ref mut some => {
69                if n == 0 {
70                    some.take()
71                } else {
72                    *some = None;
73                    self.iter.nth(n - 1)
74                }
75            }
76        }
77    }
78
79    fn all<G>(&mut self, mut f: G) -> bool
80    where
81        G: FnMut(Self::Item) -> bool,
82    {
83        if let Some(elt) = self.top.take() {
84            if !f(elt) {
85                return false;
86            }
87        }
88        self.iter.all(f)
89    }
90
91    fn fold<Acc, G>(mut self, init: Acc, mut f: G) -> Acc
92    where
93        G: FnMut(Acc, Self::Item) -> Acc,
94    {
95        let mut accum = init;
96        if let Some(elt) = self.top.take() {
97            accum = f(accum, elt);
98        }
99        self.iter.fold(accum, f)
100    }
101}