nb-tree 0.2.0-alpha01

Very simple tree structure with generic node and branch data.
Documentation
use std::marker::PhantomData;

use super::depth::Traversal;

pub struct SkipBelow<I, P, B> {
    iter: I,
    predicate: P,
    __phantom: PhantomData<B>,
}

impl<I, P, B> SkipBelow<I, P, B> {
    pub fn new(iter: I, predicate: P) -> SkipBelow<I, P, B> {
        SkipBelow {
            iter,
            predicate,
            __phantom: PhantomData,
        }
    }
}

impl<I, P, N, B> Iterator for SkipBelow<I, P, B>
where
    I: Iterator<Item = Traversal<N, B>>,
    P: FnMut(&I::Item) -> bool,
{
    type Item = I::Item;

    fn next(&mut self) -> Option<Self::Item> {
        self.iter.next().and_then(|item| self.skip(item))
    }
}

impl<I, P, N, B> SkipBelow<I, P, B>
where
    I: Iterator<Item = Traversal<N, B>>,
    P: FnMut(&I::Item) -> bool,
{
    fn skip(&mut self, item: I::Item) -> Option<I::Item> {
        let mut item = Some(item);
        let mut left_subtree = false;
        if (self.predicate)(item.as_ref().unwrap()) {
            let mut down: isize = 0;
            while {
                if let Some(next_item) = self.iter.next() {
                    // Move up
                    down -= next_item.up() as isize;
                    if down < 0 {
                        // Left filtered subtree
                        left_subtree = true;
                    }
                    let ret = if next_item.branch().is_some() {
                        // Move down
                        down += 1;
                        down > 0
                    } else {
                        down >= 0
                    };
                    if left_subtree {
                        item = Some(next_item);
                    }
                    ret
                } else {
                    false
                }
            } {}
            if left_subtree {
                if let Some(i) = item.as_mut() {
                    i.truncate_up(-down as usize)
                }
                self.skip(item.unwrap())
            } else {
                // Skipped to end
                None
            }
        } else {
            // Not skipped
            item
        }
    }
}