@@ -1484,6 +1484,79 @@ 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
+ ///
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
+
1487
1560
// Nothing should make it past this function.
1488
1561
// If there is a way for a NodeId to be invalid, it should be caught here.
1489
1562
fn is_valid_node_id ( & self , node_id : & NodeId ) -> ( bool , Option < NodeIdError > ) {
@@ -2990,4 +3063,69 @@ mod tree_tests {
2990
3063
// ensure the tree and the cloned tree are equal
2991
3064
assert_eq ! ( tree, cloned) ;
2992
3065
}
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
+ }
2993
3131
}
0 commit comments