Skip to content

Commit c07b8aa

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

File tree

2 files changed

+88
-0
lines changed

2 files changed

+88
-0
lines changed

src/lib.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,29 @@ 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+
300+
let mut queue = std::collections::VecDeque::<(NodeId, NodeId)>::new();
301+
queue.push_back((id, result.root().id));
302+
303+
while let Some((src_id, dst_id)) = queue.pop_front() {
304+
let src = unsafe { self.get_unchecked(src_id) };
305+
let mut dst = unsafe { result.get_unchecked_mut(dst_id) };
306+
for src_child in src.children() {
307+
let dst_child_id = dst.append(src_child.value().clone()).id;
308+
queue.push_back((src_child.id, dst_child_id));
309+
}
310+
}
311+
312+
result
313+
}
314+
}
315+
293316
impl<'a, T: 'a> NodeRef<'a, T> {
294317
/// Returns the ID of this node.
295318
pub fn id(&self) -> NodeId {
@@ -349,6 +372,14 @@ impl<'a, T: 'a> NodeRef<'a, T> {
349372
}
350373
}
351374

375+
impl<'a, T: 'a + Clone> NodeRef<'a, T> {
376+
/// Clones the node deeply and creates a new tree.
377+
/// Skips orphaned nodes.
378+
pub fn deep_clone(&self) -> Tree<T> {
379+
self.tree.deep_clone(self.id)
380+
}
381+
}
382+
352383
impl<'a, T: 'a> NodeMut<'a, T> {
353384
/// Returns the ID of this node.
354385
pub fn id(&self) -> NodeId {

tests/tree.rs

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,3 +238,60 @@ 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+
"child child 1",
251+
"child child 2",
252+
"child child 3",
253+
"child child 4",
254+
},
255+
},
256+
"b" => {
257+
"child 4",
258+
},
259+
}
260+
};
261+
262+
let test_node_id = tree.root().first_child().unwrap().id();
263+
let test_subtree = tree.deep_clone(test_node_id);
264+
265+
assert_eq!(
266+
test_subtree,
267+
tree! {
268+
"a" => {
269+
"child 1",
270+
"child 2",
271+
"child 3" => {
272+
"child child 1",
273+
"child child 2",
274+
"child child 3",
275+
"child child 4",
276+
},
277+
}
278+
}
279+
);
280+
281+
tree.root_mut()
282+
.first_child()
283+
.unwrap()
284+
.last_child()
285+
.unwrap()
286+
.detach();
287+
let test_subtree = tree.deep_clone(test_node_id);
288+
assert_eq!(
289+
test_subtree,
290+
tree! {
291+
"a" => {
292+
"child 1",
293+
"child 2",
294+
}
295+
}
296+
);
297+
}

0 commit comments

Comments
 (0)