gat_lending_iterator/adapters/
map_while.rs

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