Skip to content

Commit a7d3dd9

Browse files
shouyacfvescovo
authored andcommitted
Add support for appending and prepending subtree
1 parent f43f884 commit a7d3dd9

File tree

2 files changed

+72
-0
lines changed

2 files changed

+72
-0
lines changed

src/lib.rs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,28 @@ impl<T> Tree<T> {
205205
self.vec.push(Node::new(value));
206206
unsafe { self.get_unchecked_mut(id) }
207207
}
208+
209+
/// Merge with another tree as orphan, returning the new root of tree being merged.
210+
pub fn extend_tree(&mut self, mut other_tree: Tree<T>) -> NodeMut<T> {
211+
let offset = self.vec.len();
212+
let offset_id = |id: NodeId| -> NodeId {
213+
let old_index = id.to_index();
214+
let new_index = old_index + offset;
215+
unsafe { NodeId::from_index(new_index) }
216+
};
217+
let other_tree_root_id = offset_id(other_tree.root().id);
218+
for node in other_tree.vec.iter_mut() {
219+
node.parent.as_mut().map(|id| *id = offset_id(*id));
220+
node.prev_sibling.as_mut().map(|id| *id = offset_id(*id));
221+
node.next_sibling.as_mut().map(|id| *id = offset_id(*id));
222+
node.children.as_mut().map(|(id1, id2)| {
223+
*id1 = offset_id(*id1);
224+
*id2 = offset_id(*id2);
225+
});
226+
}
227+
self.vec.extend(other_tree.vec);
228+
unsafe { self.get_unchecked_mut(other_tree_root_id) }
229+
}
208230
}
209231

210232
impl<'a, T: 'a> NodeRef<'a, T> {
@@ -341,6 +363,18 @@ impl<'a, T: 'a> NodeMut<'a, T> {
341363
self.prepend_id(id)
342364
}
343365

366+
/// Appends a subtree, return the root of the merged subtree.
367+
pub fn append_subtree(&mut self, subtree: Tree<T>) -> NodeMut<T> {
368+
let root_id = self.tree.extend_tree(subtree).id;
369+
self.append_id(root_id)
370+
}
371+
372+
/// Prepends a subtree, return the root of the merged subtree.
373+
pub fn prepend_subtree(&mut self, subtree: Tree<T>) -> NodeMut<T> {
374+
let root_id = self.tree.extend_tree(subtree).id;
375+
self.prepend_id(root_id)
376+
}
377+
344378
/// Inserts a new sibling before this node.
345379
///
346380
/// # Panics

tests/subtree.rs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#[macro_use]
2+
extern crate ego_tree;
3+
4+
#[cfg(test)]
5+
mod test {
6+
#[test]
7+
fn prepend_subtree() {
8+
let mut tree = tree!('a' => { 'b', 'c' => { 'd', 'e' } });
9+
let node_id = tree.root().first_child().unwrap().id();
10+
let mut node = tree.get_mut(node_id).unwrap();
11+
assert_eq!(node.value(), &'b');
12+
13+
let subtree = tree!('f' => { 'g', 'h' => { 'i', 'j' } });
14+
let mut root_subtree = node.prepend_subtree(subtree);
15+
assert_eq!(root_subtree.parent().unwrap().value(), &'b');
16+
assert_eq!(
17+
root_subtree.parent().unwrap().parent().unwrap().value(),
18+
&'a'
19+
);
20+
21+
let new_tree = tree!('a' => { 'b' => { 'f' => { 'g', 'h' => { 'i', 'j' } } }, 'c' => { 'd', 'e' } });
22+
assert_eq!(format!("{:#?}", tree), format!("{:#?}", new_tree));
23+
}
24+
25+
#[test]
26+
fn append_subtree() {
27+
let mut tree = tree!('a' => { 'b', 'c' });
28+
let mut node = tree.root_mut();
29+
assert_eq!(node.value(), &'a');
30+
31+
let subtree = tree!('d' => { 'e', 'f' });
32+
let mut root_subtree = node.append_subtree(subtree);
33+
assert_eq!(root_subtree.parent().unwrap().value(), &'a');
34+
35+
let new_tree = tree!('a' => { 'b', 'c', 'd' => { 'e', 'f' } });
36+
assert_eq!(format!("{:#?}", tree), format!("{:#?}", new_tree));
37+
}
38+
}

0 commit comments

Comments
 (0)