nb_tree/tree/iter/
skip_below.rs

1use std::marker::PhantomData;
2
3use super::depth::Traversal;
4
5pub struct SkipBelow<I, P, B> {
6    iter: I,
7    predicate: P,
8    __phantom: PhantomData<B>,
9}
10
11impl<I, P, B> SkipBelow<I, P, B> {
12    pub fn new(iter: I, predicate: P) -> SkipBelow<I, P, B> {
13        SkipBelow {
14            iter,
15            predicate,
16            __phantom: PhantomData,
17        }
18    }
19}
20
21impl<I, P, N, B> Iterator for SkipBelow<I, P, B>
22where
23    I: Iterator<Item = Traversal<N, B>>,
24    P: FnMut(&I::Item) -> bool,
25{
26    type Item = I::Item;
27
28    fn next(&mut self) -> Option<Self::Item> {
29        self.iter.next().and_then(|item| self.skip(item))
30    }
31}
32
33impl<I, P, N, B> SkipBelow<I, P, B>
34where
35    I: Iterator<Item = Traversal<N, B>>,
36    P: FnMut(&I::Item) -> bool,
37{
38    fn skip(&mut self, item: I::Item) -> Option<I::Item> {
39        let mut item = Some(item);
40        let mut left_subtree = false;
41        if (self.predicate)(item.as_ref().unwrap()) {
42            let mut down: isize = 0;
43            while {
44                if let Some(next_item) = self.iter.next() {
45                    // Move up
46                    down -= next_item.up() as isize;
47                    if down < 0 {
48                        // Left filtered subtree
49                        left_subtree = true;
50                    }
51                    let ret = if next_item.branch().is_some() {
52                        // Move down
53                        down += 1;
54                        down > 0
55                    } else {
56                        down >= 0
57                    };
58                    if left_subtree {
59                        item = Some(next_item);
60                    }
61                    ret
62                } else {
63                    false
64                }
65            } {}
66            if left_subtree {
67                if let Some(i) = item.as_mut() {
68                    i.truncate_up(-down as usize)
69                }
70                self.skip(item.unwrap())
71            } else {
72                // Skipped to end
73                None
74            }
75        } else {
76            // Not skipped
77            item
78        }
79    }
80}