gat_lending_iterator/adapters/
scan.rs

1use crate::LendingIterator;
2use core::fmt;
3
4/// A lending iterator that maintains internal state and maps elements using that state.
5///
6/// This `struct` is created by the [`scan`] method on [`LendingIterator`]. See
7/// its documentation for more.
8///
9/// [`LendingIterator`]: crate::LendingIterator
10/// [`scan`]: crate::LendingIterator::scan
11#[derive(Clone)]
12#[must_use = "iterators are lazy and do nothing unless consumed"]
13pub struct Scan<I, St, F> {
14    iter: I,
15    f: F,
16    state: St,
17}
18
19impl<I, St, F> Scan<I, St, F> {
20    pub(crate) fn new(iter: I, state: St, f: F) -> Self {
21        Self { iter, f, state }
22    }
23}
24
25impl<I: fmt::Debug, St: fmt::Debug, F> fmt::Debug for Scan<I, St, F> {
26    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
27        f.debug_struct("Scan")
28            .field("iter", &self.iter)
29            .field("state", &self.state)
30            .finish_non_exhaustive()
31    }
32}
33
34impl<I, St, F, B> LendingIterator for Scan<I, St, F>
35where
36    I: LendingIterator,
37    F: for<'a> FnMut(&'a mut St, I::Item<'a>) -> Option<B>,
38{
39    type Item<'a>
40        = B
41    where
42        Self: 'a;
43
44    #[inline]
45    fn next(&mut self) -> Option<Self::Item<'_>> {
46        let item = self.iter.next()?;
47        (self.f)(&mut self.state, item)
48    }
49
50    #[inline]
51    fn size_hint(&self) -> (usize, Option<usize>) {
52        let (_, upper) = self.iter.size_hint();
53        (0, upper)
54    }
55}
56
57#[cfg(test)]
58mod tests {
59    use crate::{LendingIterator, ToLendingIterator};
60
61    #[test]
62    fn scan_basic() {
63        let mut result = Vec::new();
64        (1..=5)
65            .into_lending()
66            .scan(0, |state: &mut i32, x| {
67                *state += x;
68                Some(*state)
69            })
70            .for_each(|x| result.push(x));
71        assert_eq!(result, vec![1, 3, 6, 10, 15]);
72    }
73
74    #[test]
75    fn scan_early_termination() {
76        let mut result = Vec::new();
77        (1..=10)
78            .into_lending()
79            .scan(0, |state: &mut i32, x| {
80                *state += x;
81                if *state > 10 {
82                    None
83                } else {
84                    Some(*state)
85                }
86            })
87            .for_each(|x| result.push(x));
88        assert_eq!(result, vec![1, 3, 6, 10]);
89    }
90}