Skip to content

Commit 5b9331f

Browse files
committed
add map method
1 parent 6d0e5f2 commit 5b9331f

File tree

1 file changed

+138
-0
lines changed

1 file changed

+138
-0
lines changed

src/tree.rs

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

1487+
/// Returns a new `Tree` which nodes' values are mapped using the provided function.
1488+
///
1489+
/// If the mapping function returns an error it is returned immediately
1490+
/// and the process is aborted.
1491+
///
1492+
/// ```
1493+
/// # use id_tree::*;
1494+
/// # use id_tree::InsertBehavior::*;
1495+
///
1496+
/// let mut tree = Tree::new();
1497+
/// tree.insert(Node::new(1), AsRoot).unwrap();
1498+
///
1499+
/// fn map(x: i32) -> Result<i32, ()> {
1500+
/// Ok(x * 10)
1501+
/// }
1502+
///
1503+
/// let tree = tree.map(map).unwrap();
1504+
///
1505+
/// assert_eq!(10, *tree.get(&tree.root_node_id().unwrap()).unwrap().data());
1506+
/// ```
1507+
///
1508+
pub fn map<V, F, E>(mut self, mut map: F) -> Result<Tree<V>, E>
1509+
where
1510+
F: FnMut(T) -> Result<V, E>,
1511+
{
1512+
let tree_id = ProcessUniqueId::new();
1513+
1514+
Ok(Tree {
1515+
id: tree_id,
1516+
root: self.root.as_ref().map(|x| NodeId {
1517+
tree_id,
1518+
index: x.index,
1519+
}),
1520+
nodes: self
1521+
.nodes
1522+
.drain(..)
1523+
.map(|mut x| {
1524+
match x.as_mut().map(|y| {
1525+
Ok(Node {
1526+
data: map(unsafe {
1527+
std::mem::replace(&mut y.data, std::mem::zeroed())
1528+
})?,
1529+
parent: y.parent.as_ref().map(|z| NodeId {
1530+
tree_id,
1531+
index: z.index,
1532+
}),
1533+
children: y
1534+
.children
1535+
.iter()
1536+
.map(|z| NodeId {
1537+
tree_id,
1538+
index: z.index,
1539+
})
1540+
.collect(),
1541+
})
1542+
}) {
1543+
None => Ok(None),
1544+
Some(Ok(y)) => Ok(Some(y)),
1545+
Some(Err(y)) => Err(y),
1546+
}
1547+
})
1548+
.collect::<Result<_, E>>()?,
1549+
free_ids: self
1550+
.free_ids
1551+
.iter()
1552+
.map(|x| NodeId {
1553+
tree_id,
1554+
index: x.index,
1555+
})
1556+
.collect(),
1557+
})
1558+
}
1559+
14871560
// Nothing should make it past this function.
14881561
// If there is a way for a NodeId to be invalid, it should be caught here.
14891562
fn is_valid_node_id(&self, node_id: &NodeId) -> (bool, Option<NodeIdError>) {
@@ -2990,4 +3063,69 @@ mod tree_tests {
29903063
// ensure the tree and the cloned tree are equal
29913064
assert_eq!(tree, cloned);
29923065
}
3066+
3067+
#[test]
3068+
fn test_map() {
3069+
use InsertBehavior::*;
3070+
3071+
let mut tree = Tree::new();
3072+
let root_id = tree.insert(Node::new(0), AsRoot).unwrap();
3073+
let node_1_id = tree.insert(Node::new(1), UnderNode(&root_id)).unwrap();
3074+
let node_2_id = tree.insert(Node::new(2), UnderNode(&root_id)).unwrap();
3075+
let _node_3_id = tree.insert(Node::new(3), UnderNode(&node_1_id)).unwrap();
3076+
let node_4_id = tree.insert(Node::new(4), UnderNode(&node_2_id)).unwrap();
3077+
tree.take_node(node_4_id);
3078+
3079+
let tree_id = tree.id;
3080+
3081+
// ensure errors from the mapping function are propagated
3082+
assert_eq!(Err(()), tree.clone().map(|_| Err(()) as Result<(), ()>));
3083+
3084+
let mapped = tree
3085+
.map(|x| Ok(x.to_string()) as Result<String, ()>)
3086+
.unwrap();
3087+
assert!(mapped.root.is_some());
3088+
3089+
// ensure mapped tree has a new id
3090+
assert_ne!(tree_id, mapped.id);
3091+
3092+
// ensure mapped tree's root is using the new tree id
3093+
assert_eq!(mapped.root.as_ref().map(|x| x.tree_id), Some(mapped.id));
3094+
3095+
// ensure mapped tree's free_ids is using the new tree id
3096+
assert_eq!(mapped.free_ids[0].tree_id, mapped.id);
3097+
3098+
// ensure nodes' parent are using the new tree id
3099+
assert_eq!(
3100+
mapped.nodes[1]
3101+
.as_ref()
3102+
.map(|x| x.parent.as_ref().map(|x| x.tree_id)),
3103+
Some(Some(mapped.id))
3104+
);
3105+
3106+
// ensure nodes' children are using the new tree id
3107+
assert_eq!(
3108+
mapped
3109+
.children(mapped.root.as_ref().unwrap())
3110+
.unwrap()
3111+
.next()
3112+
.map(|x| x.parent.as_ref().map(|x| x.tree_id)),
3113+
Some(Some(mapped.id))
3114+
);
3115+
3116+
// ensure the mapping is correct
3117+
assert_eq!(
3118+
mapped
3119+
.traverse_level_order(mapped.root.as_ref().unwrap())
3120+
.unwrap()
3121+
.map(Node::data)
3122+
.collect::<Vec<_>>(),
3123+
vec![
3124+
&0.to_string(),
3125+
&1.to_string(),
3126+
&2.to_string(),
3127+
&3.to_string()
3128+
]
3129+
);
3130+
}
29933131
}

0 commit comments

Comments
 (0)