Skip to content

Commit 69e02d6

Browse files
committed
Added deep_clone for nodes
1 parent 2a90702 commit 69e02d6

File tree

2 files changed

+75
-0
lines changed

2 files changed

+75
-0
lines changed

src/lib.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,26 @@ impl<T> Tree<T> {
290290
}
291291
}
292292

293+
impl<T: Clone> Tree<T> {
294+
/// Clones the node deeply and creates a new tree.
295+
/// Skips orphaned nodes.
296+
pub fn deep_clone(&self, id: NodeId) -> Self {
297+
let start_node = unsafe { self.get_unchecked(id) };
298+
let mut result = Self::new(start_node.value().clone());
299+
let mut id_map = std::collections::HashMap::new();
300+
id_map.insert(start_node.id, result.root().id);
301+
302+
for orig in start_node.descendants() {
303+
let copy_id = id_map.get(&orig.id).unwrap();
304+
let mut copy = unsafe { result.get_unchecked_mut(*copy_id) };
305+
for child in orig.children() {
306+
id_map.insert(child.id, copy.append(child.value().clone()).id);
307+
}
308+
}
309+
result
310+
}
311+
}
312+
293313
impl<'a, T: 'a> NodeRef<'a, T> {
294314
/// Returns the ID of this node.
295315
pub fn id(&self) -> NodeId {
@@ -349,6 +369,14 @@ impl<'a, T: 'a> NodeRef<'a, T> {
349369
}
350370
}
351371

372+
impl<'a, T: 'a + Clone> NodeRef<'a, T> {
373+
/// Clones the node deeply and creates a new tree.
374+
/// Skips orphaned nodes.
375+
pub fn deep_clone(&self) -> Tree<T> {
376+
self.tree.deep_clone(self.id)
377+
}
378+
}
379+
352380
impl<'a, T: 'a> NodeMut<'a, T> {
353381
/// Returns the ID of this node.
354382
pub fn id(&self) -> NodeId {

tests/tree.rs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,3 +238,50 @@ fn test_display() {
238238

239239
assert_eq!(repr, expected);
240240
}
241+
242+
#[test]
243+
fn clone_subtree() {
244+
let mut tree = tree! {
245+
"root" => {
246+
"a" => {
247+
"child 1",
248+
"child 2",
249+
"child 3",
250+
},
251+
"b" => {
252+
"child 4",
253+
},
254+
}
255+
};
256+
257+
let test_node_id = tree.root().first_child().unwrap().id();
258+
let test_subtree = tree.deep_clone(test_node_id);
259+
260+
assert_eq!(
261+
test_subtree,
262+
tree! {
263+
"a" => {
264+
"child 1",
265+
"child 2",
266+
"child 3",
267+
}
268+
}
269+
);
270+
271+
tree.root_mut()
272+
.first_child()
273+
.unwrap()
274+
.last_child()
275+
.unwrap()
276+
.detach();
277+
let test_subtree = tree.deep_clone(test_node_id);
278+
assert_eq!(
279+
test_subtree,
280+
tree! {
281+
"a" => {
282+
"child 1",
283+
"child 2",
284+
}
285+
}
286+
);
287+
}

0 commit comments

Comments
 (0)