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