gat_lending_iterator/adapters/
skip_while.rs

1use crate::LendingIterator;
2use core::fmt;
3
4/// A lending iterator that that rejects elements while `predicate` returns `true`.
5#[derive(Clone)]
6#[must_use = "iterators are lazy and do nothing unless consumed"]
7pub struct SkipWhile<I, P> {
8    iter: I,
9    flag: bool,
10    predicate: P,
11}
12
13impl<I, P> SkipWhile<I, P> {
14    pub(crate) fn new(iter: I, predicate: P) -> Self {
15        Self {
16            iter,
17            flag: false,
18            predicate,
19        }
20    }
21}
22
23impl<I: fmt::Debug, P> fmt::Debug for SkipWhile<I, P> {
24    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
25        f.debug_struct("SkipWhile")
26            .field("iter", &self.iter)
27            .field("flag", &self.flag)
28            .finish_non_exhaustive()
29    }
30}
31
32impl<I, P> LendingIterator for SkipWhile<I, P>
33where
34    I: LendingIterator,
35    P: for<'a> FnMut(&I::Item<'a>) -> bool,
36{
37    type Item<'a>
38        = I::Item<'a>
39    where
40        Self: 'a;
41
42    #[inline]
43    fn next(&mut self) -> Option<Self::Item<'_>> {
44        if self.flag {
45            return self.iter.next();
46        }
47        loop {
48            // SAFETY: see https://docs.rs/polonius-the-crab/0.3.1/polonius_the_crab/#the-arcanemagic
49            let self_ = unsafe { &mut *(self as *mut Self) };
50            if let Some(item) = self_.iter.next() {
51                if !(self_.predicate)(&item) {
52                    self_.flag = true;
53                    return Some(item);
54                }
55            } else {
56                return None;
57            }
58        }
59    }
60
61    #[inline]
62    fn size_hint(&self) -> (usize, Option<usize>) {
63        let (_, upper) = self.iter.size_hint();
64        (0, upper) // can't know a lower bound, due to the predicate
65    }
66
67    // TODO: there's a `fold` optimization possible here,
68    // but for some reason the lifetimes don't type check
69}
70
71#[cfg(test)]
72mod tests {
73    use crate::{LendingIterator, ToLendingIterator};
74
75    fn identity(x: i32) -> i32 {
76        x
77    }
78
79    #[test]
80    fn skip_while_basic() {
81        let result: Vec<_> = (0..10)
82            .into_lending()
83            .skip_while(|&x| x < 5)
84            .map(identity)
85            .into_iter()
86            .collect();
87        assert_eq!(result, vec![5, 6, 7, 8, 9]);
88    }
89}