Skip to content

Commit 4a8aabb

Browse files
committed
Add traverse functions for NodeMut
1 parent ecd16e5 commit 4a8aabb

File tree

2 files changed

+186
-0
lines changed

2 files changed

+186
-0
lines changed

src/lib.rs

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -369,6 +369,11 @@ impl<'a, T: 'a> NodeMut<'a, T> {
369369
&mut self.node().value
370370
}
371371

372+
/// Downcast `NodeMut` to `NodeRef`.
373+
pub fn as_ref(&mut self) -> NodeRef<'_, T> {
374+
unsafe { self.tree.get_unchecked(self.id) }
375+
}
376+
372377
fn axis<F>(&mut self, f: F) -> Option<NodeMut<T>>
373378
where
374379
F: FnOnce(&mut Node<T>) -> Option<NodeId>,
@@ -463,6 +468,116 @@ impl<'a, T: 'a> NodeMut<'a, T> {
463468
unsafe { self.tree.get_unchecked(self.id).has_children() }
464469
}
465470

471+
/// Apply function for each ancestor mutable node reference.
472+
pub fn for_each_ancestor<'b, F>(&'b mut self, mut f: F)
473+
where
474+
F: FnMut(&mut NodeMut<'b, T>),
475+
{
476+
let mut current = self.parent();
477+
while let Some(mut node) = current {
478+
f(&mut node);
479+
current = node.into_parent().ok();
480+
}
481+
}
482+
483+
/// Apply function for each next sibling mutable node reference.
484+
pub fn for_each_next_sibling<'b, F>(&'b mut self, mut f: F)
485+
where
486+
F: FnMut(&mut NodeMut<'b, T>),
487+
{
488+
let mut current = self.next_sibling();
489+
while let Some(mut node) = current {
490+
f(&mut node);
491+
current = node.into_next_sibling().ok();
492+
}
493+
}
494+
495+
/// Apply function for each previout sibling mutable node reference.
496+
pub fn for_each_prev_sibling<'b, F>(&'b mut self, mut f: F)
497+
where
498+
F: FnMut(&mut NodeMut<'b, T>),
499+
{
500+
let mut current = self.prev_sibling();
501+
while let Some(mut node) = current {
502+
f(&mut node);
503+
current = node.into_prev_sibling().ok();
504+
}
505+
}
506+
507+
/// Apply function for this node and each sibling mutable node reference.
508+
pub fn for_each_sibling<F>(&mut self, mut f: F)
509+
where
510+
F: for<'b> FnMut(&mut NodeMut<'b, T>),
511+
{
512+
self.for_each_prev_sibling(&mut f);
513+
f(self);
514+
self.for_each_next_sibling(&mut f);
515+
}
516+
517+
/// Apply function for each children mutable node reference.
518+
pub fn for_each_child<F>(&mut self, mut f: F)
519+
where
520+
F: for<'b> FnMut(&mut NodeMut<'b, T>),
521+
{
522+
let Some(mut first_child) = self.first_child() else {
523+
return;
524+
};
525+
f(&mut first_child);
526+
first_child.for_each_next_sibling(f);
527+
}
528+
529+
/// Apply function for this node and each descendant mutable node reference.
530+
pub fn for_each_descendant<F>(&mut self, mut f: F)
531+
where
532+
F: FnMut(&mut NodeMut<'_, T>),
533+
{
534+
let id = self.id();
535+
536+
f(self);
537+
538+
// Start at our first child, if any.
539+
let Some(mut node) = self.first_child() else {
540+
return;
541+
};
542+
543+
loop {
544+
f(&mut node);
545+
546+
// Try to go deeper into its first child.
547+
match node.into_first_child() {
548+
Ok(child) => {
549+
node = child;
550+
continue;
551+
}
552+
Err(n) => {
553+
node = n;
554+
}
555+
}
556+
557+
// No deeper child, so climb until we find a next sibling or hit self.
558+
loop {
559+
match node.into_next_sibling() {
560+
Ok(sib) => {
561+
node = sib;
562+
break;
563+
}
564+
Err(n) => {
565+
node = n;
566+
}
567+
}
568+
569+
// No sibling, so climb up.
570+
let Ok(parent) = node.into_parent() else {
571+
unreachable!();
572+
};
573+
if parent.id() == id {
574+
return;
575+
}
576+
node = parent;
577+
}
578+
}
579+
}
580+
466581
/// Appends a new child to this node.
467582
pub fn append(&mut self, value: T) -> NodeMut<T> {
468583
let id = self.tree.orphan(value).id;

tests/node_mut.rs

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,77 @@ fn has_children() {
7474
assert!(!tree.root_mut().first_child().unwrap().has_children());
7575
}
7676

77+
#[test]
78+
fn for_each_next_sibling() {
79+
let mut tree = tree!(1 => { 2, 3, 4, 5, 6 });
80+
let mut root = tree.root_mut();
81+
let mut c = root.first_child().unwrap();
82+
83+
c.for_each_next_sibling(|n| {
84+
*n.value() += 1;
85+
});
86+
87+
let res = tree!(1 => { 2, 4, 5, 6, 7 });
88+
89+
assert_eq!(tree, res);
90+
}
91+
92+
#[test]
93+
fn for_each_prev_sibling() {
94+
let mut tree = tree!(1 => { 2, 3, 4, 5, 6 });
95+
let mut root = tree.root_mut();
96+
let mut c = root.last_child().unwrap();
97+
98+
c.for_each_prev_sibling(|n| {
99+
*n.value() += 1;
100+
});
101+
102+
let res = tree!(1 => { 3, 4, 5, 6, 6 });
103+
104+
assert_eq!(tree, res);
105+
}
106+
107+
#[test]
108+
fn for_each_sibling() {
109+
let rt = 2;
110+
let mut tree = tree!(rt => { 2, 3, 4, 5, 6 });
111+
let mut root = tree.root_mut();
112+
let mut c = root.last_child().unwrap();
113+
114+
c.for_each_sibling(|n| {
115+
let v = n.parent().map(|mut p| *p.value()).unwrap();
116+
*n.value() += v;
117+
});
118+
119+
let res = tree!(rt => { 4, 5, 6, 7, 8 });
120+
121+
assert_eq!(tree, res);
122+
}
123+
124+
#[test]
125+
fn for_each_child() {
126+
let mut tree = tree!(1 => { 2, 3, 4, 5, 6 });
127+
let mut root = tree.root_mut();
128+
root.for_each_child(|n| *n.value() += 1);
129+
130+
assert_eq!(*root.value(), 1);
131+
132+
let res = tree!(1 => { 3, 4, 5, 6, 7 });
133+
134+
assert_eq!(tree, res);
135+
}
136+
137+
#[test]
138+
fn for_each_descendant() {
139+
let mut tree = tree!(1 => { 2 => {3, 4, 5, 6}, 3, 4 => {0, 1}, 5, 6 => {1, 2} });
140+
let mut root = tree.root_mut();
141+
root.for_each_descendant(|n| *n.value() += 1);
142+
143+
let tree2 = tree!(2 => { 3 => {4, 5, 6, 7}, 4, 5 => {1, 2}, 6, 7 => {2, 3} });
144+
145+
assert_eq!(tree, tree2);
146+
}
147+
77148
#[test]
78149
fn append_1() {
79150
let mut tree = tree!('a');

0 commit comments

Comments
 (0)