treeclimber 0.0.1

An iterator that climbs trees.
Documentation
use crate::bfs::Bfs;
use crate::dfs::Dfs;
use crate::postorder::Postorder;

pub mod bfs;
pub mod dfs;
pub mod postorder;
pub mod prelude;

pub trait Climber: Iterator {
    fn depth(&self) -> usize;
    fn up(&mut self) -> Option<Self::Item>;
    fn down<P>(&mut self, predicate: P) -> Option<Self::Item>
    where
        P: FnMut(&Self::Item) -> bool;
    fn parent(&self) -> Option<Self::Item>;
    fn children(&self) -> impl Iterator<Item = Self::Item>;

    fn is_leaf(&self) -> bool {
        self.children().next().is_none()
    }
    fn is_root(&self) -> bool {
        self.depth() == 0
    }
    fn has_parent(&self) -> bool {
        self.parent().is_some()
    }
    fn has_children(&self) -> bool {
        self.children().next().is_some()
    }
    fn child_count(&self) -> usize {
        self.children().count()
    }
    fn find_child<P>(&self, predicate: P) -> Option<Self::Item>
    where
        P: FnMut(&Self::Item) -> bool,
    {
        self.children().find(predicate)
    }
    fn ancestors(&mut self) -> impl Iterator<Item = Self::Item> + '_ {
        std::iter::from_fn(|| self.up())
    }
    fn find_ancestor<P>(&mut self, mut predicate: P) -> Option<Self::Item>
    where
        P: FnMut(&Self::Item) -> bool,
    {
        self.ancestors().find(|node| predicate(node))
    }
    fn has_ancestor<P>(&mut self, predicate: P) -> bool
    where
        P: FnMut(&Self::Item) -> bool,
    {
        self.find_ancestor(predicate).is_some()
    }
    fn to_root(&mut self) {
        while self.up().is_some() {}
    }
    fn up_by(&mut self, levels: usize) {
        for _ in 0..levels {
            if self.up().is_none() {
                break;
            }
        }
    }
    fn up_until<P>(&mut self, mut predicate: P) -> Option<Self::Item>
    where
        P: FnMut(&Self::Item) -> bool,
    {
        while let Some(node) = self.up() {
            if predicate(&node) {
                return Some(node);
            }
        }
        None
    }
    fn down_until<P, Q>(&mut self, mut descend: P, mut until: Q) -> Option<Self::Item>
    where
        P: FnMut(&Self::Item) -> bool,
        Q: FnMut(&Self::Item) -> bool,
    {
        loop {
            let node = self.down(&mut descend)?;

            if until(&node) {
                return Some(node);
            }
        }
    }
}

pub trait IndexedClimber: Climber {
    type Index;
    fn index(&self) -> Self::Index;
    fn go_to(&mut self, index: &Self::Index) -> Option<Self::Item>;
    fn child_indices(&self) -> impl DoubleEndedIterator<Item = Self::Index>;
    fn dfs(self) -> Dfs<Self>
    where
        Self: Sized,
    {
        Dfs::new(self)
    }

    fn bfs(self) -> Bfs<Self>
    where
        Self: Sized,
    {
        Bfs::new(self)
    }
    fn postorder(self) -> Postorder<Self>
    where
        Self: Sized,
    {
        Postorder::new(self)
    }
}