@@ -1484,6 +1484,58 @@ impl<T> Tree<T> {
1484
1484
Ok ( LevelOrderTraversalIds :: new ( self , node_id. clone ( ) ) )
1485
1485
}
1486
1486
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
+
1487
1539
// Nothing should make it past this function.
1488
1540
// If there is a way for a NodeId to be invalid, it should be caught here.
1489
1541
fn is_valid_node_id ( & self , node_id : & NodeId ) -> ( bool , Option < NodeIdError > ) {
@@ -2990,4 +3042,69 @@ mod tree_tests {
2990
3042
// ensure the tree and the cloned tree are equal
2991
3043
assert_eq ! ( tree, cloned) ;
2992
3044
}
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
+ }
2993
3110
}
0 commit comments