indextree
indextree copied to clipboard
Feature Request Walker Iterator
trafficstars
Hi, Would it possible to add a walker iterator that takes a function and advance based on Control value. this is very similar to petgraph dfs
pub enum WalkerState {
Continue,
Break,
// Stop ?
}
pub struct Walker<'a, T, F> {
arena: &'a Arena<T>,
root: NodeId,
next: Option<NodeEdge>,
val: F,
}
impl<'a, T, F> Walker<'a, T, F>
where
F: Fn(&Node<T>) -> WalkerState,
{
pub fn new(arena: &'a Arena<T>, current: NodeId, val: F) -> Self {
Self {
arena,
root: current,
next: Some(NodeEdge::Start(current)),
val,
}
}
#[must_use]
pub fn next_traverse(&self, next: NodeEdge) -> Option<NodeEdge> {
match next {
NodeEdge::Start(node) => {
match (self.arena[node].first_child(), (self.val)(&self.arena[node]),) {
(Some(first_child), WalkerState::Continue) => {
Some(NodeEdge::Start(first_child))
}
(_, _) => Some(NodeEdge::End(node)),
}
}
NodeEdge::End(node) => {
let node = &self.arena[node];
match node.next_sibling() {
Some(next_sibling) => Some(NodeEdge::Start(next_sibling)),
None => node.parent().map(NodeEdge::End),
}
}
}
}
/// Calculates the next node.
fn next_of_next(&self, next: NodeEdge) -> Option<NodeEdge> {
if next == NodeEdge::End(self.root) {
return None;
}
self.next_traverse(next)
}
}
impl<T, F> Iterator for Walker<'_, T, F>
where
F: Fn(&Node<T>) -> WalkerState,
{
type Item = NodeEdge;
fn next(&mut self) -> Option<NodeEdge> {
let next = self.next.take()?;
self.next = self.next_of_next(next);
Some(next)
}
}
@nchouba thank you for the feature request! It sounds valuable to me, do you consider to propose the changes as PR?