Skip to content

Commit 1a2ff39

Browse files
committed
add map method
1 parent 6d0e5f2 commit 1a2ff39

File tree

1 file changed

+117
-0
lines changed

1 file changed

+117
-0
lines changed

src/tree.rs

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1484,6 +1484,58 @@ impl<T> Tree<T> {
14841484
Ok(LevelOrderTraversalIds::new(self, node_id.clone()))
14851485
}
14861486

1487+
pub fn map<V, F, E>(mut self, mut map: F) -> Result<Tree<V>, E>
1488+
where
1489+
F: FnMut(T) -> Result<V, E>,
1490+
{
1491+
let tree_id = ProcessUniqueId::new();
1492+
1493+
Ok(Tree {
1494+
id: tree_id,
1495+
root: self.root.as_ref().map(|x| NodeId {
1496+
tree_id,
1497+
index: x.index,
1498+
}),
1499+
nodes: self
1500+
.nodes
1501+
.drain(..)
1502+
.map(|mut x| {
1503+
match x.as_mut().map(|y| {
1504+
Ok(Node {
1505+
data: map(unsafe {
1506+
std::mem::replace(&mut y.data, std::mem::zeroed())
1507+
})?,
1508+
parent: y.parent.as_ref().map(|z| NodeId {
1509+
tree_id,
1510+
index: z.index,
1511+
}),
1512+
children: y
1513+
.children
1514+
.iter()
1515+
.map(|z| NodeId {
1516+
tree_id,
1517+
index: z.index,
1518+
})
1519+
.collect(),
1520+
})
1521+
}) {
1522+
None => Ok(None),
1523+
Some(Ok(y)) => Ok(Some(y)),
1524+
Some(Err(y)) => Err(y),
1525+
}
1526+
})
1527+
.collect::<Result<_, E>>()?,
1528+
free_ids: self
1529+
.free_ids
1530+
.iter()
1531+
.map(|x| NodeId {
1532+
tree_id,
1533+
index: x.index,
1534+
})
1535+
.collect(),
1536+
})
1537+
}
1538+
14871539
// Nothing should make it past this function.
14881540
// If there is a way for a NodeId to be invalid, it should be caught here.
14891541
fn is_valid_node_id(&self, node_id: &NodeId) -> (bool, Option<NodeIdError>) {
@@ -2990,4 +3042,69 @@ mod tree_tests {
29903042
// ensure the tree and the cloned tree are equal
29913043
assert_eq!(tree, cloned);
29923044
}
3045+
3046+
#[test]
3047+
fn test_map() {
3048+
use InsertBehavior::*;
3049+
3050+
let mut tree = Tree::new();
3051+
let root_id = tree.insert(Node::new(0), AsRoot).unwrap();
3052+
let node_1_id = tree.insert(Node::new(1), UnderNode(&root_id)).unwrap();
3053+
let node_2_id = tree.insert(Node::new(2), UnderNode(&root_id)).unwrap();
3054+
let _node_3_id = tree.insert(Node::new(3), UnderNode(&node_1_id)).unwrap();
3055+
let node_4_id = tree.insert(Node::new(4), UnderNode(&node_2_id)).unwrap();
3056+
tree.take_node(node_4_id);
3057+
3058+
let tree_id = tree.id;
3059+
3060+
// ensure errors from the mapping function are propagated
3061+
assert_eq!(Err(()), tree.clone().map(|_| Err(()) as Result<(), ()>));
3062+
3063+
let mapped = tree
3064+
.map(|x| Ok(x.to_string()) as Result<String, ()>)
3065+
.unwrap();
3066+
assert!(mapped.root.is_some());
3067+
3068+
// ensure mapped tree has a new id
3069+
assert_ne!(tree_id, mapped.id);
3070+
3071+
// ensure mapped tree's root is using the new tree id
3072+
assert_eq!(mapped.root.as_ref().map(|x| x.tree_id), Some(mapped.id));
3073+
3074+
// ensure mapped tree's free_ids is using the new tree id
3075+
assert_eq!(mapped.free_ids[0].tree_id, mapped.id);
3076+
3077+
// ensure nodes' parent are using the new tree id
3078+
assert_eq!(
3079+
mapped.nodes[1]
3080+
.as_ref()
3081+
.map(|x| x.parent.as_ref().map(|x| x.tree_id)),
3082+
Some(Some(mapped.id))
3083+
);
3084+
3085+
// ensure nodes' children are using the new tree id
3086+
assert_eq!(
3087+
mapped
3088+
.children(mapped.root.as_ref().unwrap())
3089+
.unwrap()
3090+
.next()
3091+
.map(|x| x.parent.as_ref().map(|x| x.tree_id)),
3092+
Some(Some(mapped.id))
3093+
);
3094+
3095+
// ensure the mapping is correct
3096+
assert_eq!(
3097+
mapped
3098+
.traverse_level_order(mapped.root.as_ref().unwrap())
3099+
.unwrap()
3100+
.map(Node::data)
3101+
.collect::<Vec<_>>(),
3102+
vec![
3103+
&0.to_string(),
3104+
&1.to_string(),
3105+
&2.to_string(),
3106+
&3.to_string()
3107+
]
3108+
);
3109+
}
29933110
}

0 commit comments

Comments
 (0)