Skip to content

Add traverse functions for NodeMut #45

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 18, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
115 changes: 115 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,11 @@ impl<'a, T: 'a> NodeMut<'a, T> {
&mut self.node().value
}

/// Downcast `NodeMut` to `NodeRef`.
pub fn as_ref(&mut self) -> NodeRef<'_, T> {
unsafe { self.tree.get_unchecked(self.id) }
}

fn axis<F>(&mut self, f: F) -> Option<NodeMut<T>>
where
F: FnOnce(&mut Node<T>) -> Option<NodeId>,
Expand Down Expand Up @@ -463,6 +468,116 @@ impl<'a, T: 'a> NodeMut<'a, T> {
unsafe { self.tree.get_unchecked(self.id).has_children() }
}

/// Apply function for each ancestor mutable node reference.
pub fn for_each_ancestor<'b, F>(&'b mut self, mut f: F)
where
F: FnMut(&mut NodeMut<'b, T>),
{
let mut current = self.parent();
while let Some(mut node) = current {
f(&mut node);
current = node.into_parent().ok();
}
}

/// Apply function for each next sibling mutable node reference.
pub fn for_each_next_sibling<'b, F>(&'b mut self, mut f: F)
where
F: FnMut(&mut NodeMut<'b, T>),
{
let mut current = self.next_sibling();
while let Some(mut node) = current {
f(&mut node);
current = node.into_next_sibling().ok();
}
}

/// Apply function for each previout sibling mutable node reference.
pub fn for_each_prev_sibling<'b, F>(&'b mut self, mut f: F)
where
F: FnMut(&mut NodeMut<'b, T>),
{
let mut current = self.prev_sibling();
while let Some(mut node) = current {
f(&mut node);
current = node.into_prev_sibling().ok();
}
}

/// Apply function for this node and each sibling mutable node reference.
pub fn for_each_sibling<F>(&mut self, mut f: F)
where
F: for<'b> FnMut(&mut NodeMut<'b, T>),
{
self.for_each_prev_sibling(&mut f);
f(self);
self.for_each_next_sibling(&mut f);
}

/// Apply function for each children mutable node reference.
pub fn for_each_child<F>(&mut self, mut f: F)
where
F: for<'b> FnMut(&mut NodeMut<'b, T>),
{
let Some(mut first_child) = self.first_child() else {
return;
};
f(&mut first_child);
first_child.for_each_next_sibling(f);
}

/// Apply function for this node and each descendant mutable node reference.
pub fn for_each_descendant<F>(&mut self, mut f: F)
where
F: FnMut(&mut NodeMut<'_, T>),
{
let id = self.id();

f(self);

// Start at our first child, if any.
let Some(mut node) = self.first_child() else {
return;
};

loop {
f(&mut node);

// Try to go deeper into its first child.
match node.into_first_child() {
Ok(child) => {
node = child;
continue;
}
Err(n) => {
node = n;
}
}

// No deeper child, so climb until we find a next sibling or hit self.
loop {
match node.into_next_sibling() {
Ok(sib) => {
node = sib;
break;
}
Err(n) => {
node = n;
}
}

// No sibling, so climb up.
let Ok(parent) = node.into_parent() else {
unreachable!();
};
if parent.id() == id {
return;
}
node = parent;
}
}
}

/// Appends a new child to this node.
pub fn append(&mut self, value: T) -> NodeMut<T> {
let id = self.tree.orphan(value).id;
Expand Down
71 changes: 71 additions & 0 deletions tests/node_mut.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,77 @@ fn has_children() {
assert!(!tree.root_mut().first_child().unwrap().has_children());
}

#[test]
fn for_each_next_sibling() {
let mut tree = tree!(1 => { 2, 3, 4, 5, 6 });
let mut root = tree.root_mut();
let mut c = root.first_child().unwrap();

c.for_each_next_sibling(|n| {
*n.value() += 1;
});

let res = tree!(1 => { 2, 4, 5, 6, 7 });

assert_eq!(tree, res);
}

#[test]
fn for_each_prev_sibling() {
let mut tree = tree!(1 => { 2, 3, 4, 5, 6 });
let mut root = tree.root_mut();
let mut c = root.last_child().unwrap();

c.for_each_prev_sibling(|n| {
*n.value() += 1;
});

let res = tree!(1 => { 3, 4, 5, 6, 6 });

assert_eq!(tree, res);
}

#[test]
fn for_each_sibling() {
let rt = 2;
let mut tree = tree!(rt => { 2, 3, 4, 5, 6 });
let mut root = tree.root_mut();
let mut c = root.last_child().unwrap();

c.for_each_sibling(|n| {
let v = n.parent().map(|mut p| *p.value()).unwrap();
*n.value() += v;
});

let res = tree!(rt => { 4, 5, 6, 7, 8 });

assert_eq!(tree, res);
}

#[test]
fn for_each_child() {
let mut tree = tree!(1 => { 2, 3, 4, 5, 6 });
let mut root = tree.root_mut();
root.for_each_child(|n| *n.value() += 1);

assert_eq!(*root.value(), 1);

let res = tree!(1 => { 3, 4, 5, 6, 7 });

assert_eq!(tree, res);
}

#[test]
fn for_each_descendant() {
let mut tree = tree!(1 => { 2 => {3, 4, 5, 6}, 3, 4 => {0, 1}, 5, 6 => {1, 2} });
let mut root = tree.root_mut();
root.for_each_descendant(|n| *n.value() += 1);

let tree2 = tree!(2 => { 3 => {4, 5, 6, 7}, 4, 5 => {1, 2}, 6, 7 => {2, 3} });

assert_eq!(tree, tree2);
}

#[test]
fn append_1() {
let mut tree = tree!('a');
Expand Down