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() {
down -= next_item.up() as isize;
if down < 0 {
left_subtree = true;
}
let ret = if next_item.branch().is_some() {
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 {
None
}
} else {
item
}
}
}