@@ -22,7 +22,7 @@ struct TreeIndexMap {
2222}
2323
2424impl TreeIndexMap {
25- fn get_index ( & mut self , id : TreeId ) -> TreeIndex {
25+ fn get_or_create_index ( & mut self , id : TreeId ) -> TreeIndex {
2626 * self . id_to_index . entry ( id) . or_insert_with ( || {
2727 let tree_index = TreeIndex ( self . next ) ;
2828 self . next += 1 ;
@@ -31,6 +31,10 @@ impl TreeIndexMap {
3131 } )
3232 }
3333
34+ fn get_index ( & self , id : TreeId ) -> Option < TreeIndex > {
35+ self . id_to_index . get ( & id) . copied ( )
36+ }
37+
3438 fn get_id ( & self , index : TreeIndex ) -> Option < TreeId > {
3539 self . index_to_id . get ( & index) . copied ( )
3640 }
@@ -110,7 +114,7 @@ impl State {
110114 is_host_focused : bool ,
111115 mut changes : Option < & mut InternalChanges > ,
112116 ) {
113- let tree_index = self . tree_index_map . get_index ( update. tree_id ) ;
117+ let tree_index = self . tree_index_map . get_or_create_index ( update. tree_id ) ;
114118 let map_id = |id : LocalNodeId | NodeId :: new ( id, tree_index) ;
115119
116120 let mut unreachable = HashSet :: new ( ) ;
@@ -509,6 +513,15 @@ impl State {
509513 } )
510514 }
511515
516+ pub fn node_by_tree_local_id (
517+ & self ,
518+ local_node_id : LocalNodeId ,
519+ tree_id : TreeId ,
520+ ) -> Option < Node < ' _ > > {
521+ let tree_index = self . tree_index_map . get_index ( tree_id) ?;
522+ self . node_by_id ( NodeId :: new ( local_node_id, tree_index) )
523+ }
524+
512525 pub fn root_id ( & self ) -> NodeId {
513526 self . root
514527 }
@@ -599,7 +612,7 @@ impl Tree {
599612 panic ! ( "Cannot initialize with a subtree. TreeUpdate::tree_id must be TreeId::ROOT." ) ;
600613 }
601614 let mut tree_index_map = TreeIndexMap :: default ( ) ;
602- let tree_index = tree_index_map. get_index ( initial_state. tree_id ) ;
615+ let tree_index = tree_index_map. get_or_create_index ( initial_state. tree_id ) ;
603616 let mut state = State {
604617 nodes : HashMap :: new ( ) ,
605618 root : NodeId :: new ( tree. root , tree_index) ,
@@ -761,9 +774,9 @@ mod tests {
761774 let id2 = TreeId ( Uuid :: from_u128 ( 1 ) ) ;
762775 let id3 = TreeId ( Uuid :: from_u128 ( 2 ) ) ;
763776
764- let index1 = map. get_index ( id1) ;
765- let index2 = map. get_index ( id2) ;
766- let index3 = map. get_index ( id3) ;
777+ let index1 = map. get_or_create_index ( id1) ;
778+ let index2 = map. get_or_create_index ( id2) ;
779+ let index3 = map. get_or_create_index ( id3) ;
767780
768781 assert_eq ! ( index1, TreeIndex ( 0 ) ) ;
769782 assert_eq ! ( index2, TreeIndex ( 1 ) ) ;
@@ -775,8 +788,8 @@ mod tests {
775788 let mut map = TreeIndexMap :: default ( ) ;
776789 let id = TreeId :: ROOT ;
777790
778- let index1 = map. get_index ( id) ;
779- let index2 = map. get_index ( id) ;
791+ let index1 = map. get_or_create_index ( id) ;
792+ let index2 = map. get_or_create_index ( id) ;
780793
781794 assert_eq ! ( index1, index2) ;
782795 }
@@ -787,8 +800,8 @@ mod tests {
787800 let id1 = TreeId :: ROOT ;
788801 let id2 = TreeId ( Uuid :: from_u128 ( 1 ) ) ;
789802
790- let index1 = map. get_index ( id1) ;
791- let index2 = map. get_index ( id2) ;
803+ let index1 = map. get_or_create_index ( id1) ;
804+ let index2 = map. get_or_create_index ( id2) ;
792805
793806 assert_eq ! ( map. get_id( index1) , Some ( id1) ) ;
794807 assert_eq ! ( map. get_id( index2) , Some ( id2) ) ;
@@ -801,6 +814,38 @@ mod tests {
801814 assert_eq ! ( map. get_id( TreeIndex ( 999 ) ) , None ) ;
802815 }
803816
817+ #[ test]
818+ fn tree_index_map_get_index_returns_existing_index ( ) {
819+ let mut map = TreeIndexMap :: default ( ) ;
820+ let id1 = TreeId :: ROOT ;
821+ let id2 = TreeId ( Uuid :: from_u128 ( 1 ) ) ;
822+
823+ let created1 = map. get_or_create_index ( id1) ;
824+ let created2 = map. get_or_create_index ( id2) ;
825+
826+ assert_eq ! ( map. get_index( id1) , Some ( created1) ) ;
827+ assert_eq ! ( map. get_index( id2) , Some ( created2) ) ;
828+ }
829+
830+ #[ test]
831+ fn tree_index_map_get_index_returns_none_for_unknown_id ( ) {
832+ let map = TreeIndexMap :: default ( ) ;
833+ assert_eq ! ( map. get_index( TreeId :: ROOT ) , None ) ;
834+ assert_eq ! ( map. get_index( TreeId ( Uuid :: from_u128( 42 ) ) ) , None ) ;
835+ }
836+
837+ #[ test]
838+ fn tree_index_map_get_index_does_not_create_mapping ( ) {
839+ let mut map = TreeIndexMap :: default ( ) ;
840+ let unknown = TreeId ( Uuid :: from_u128 ( 7 ) ) ;
841+
842+ assert_eq ! ( map. get_index( unknown) , None ) ;
843+
844+ let first = map. get_or_create_index ( TreeId :: ROOT ) ;
845+ assert_eq ! ( first, TreeIndex ( 0 ) ) ;
846+ assert_eq ! ( map. get_index( unknown) , None ) ;
847+ }
848+
804849 #[ test]
805850 fn init_tree_with_root_node ( ) {
806851 let update = TreeUpdate {
@@ -1562,6 +1607,128 @@ mod tests {
15621607 NodeId :: new ( LocalNodeId ( id) , TreeIndex ( 1 ) )
15631608 }
15641609
1610+ #[ test]
1611+ fn node_by_tree_local_id_finds_root_tree_node ( ) {
1612+ let update = TreeUpdate {
1613+ nodes : vec ! [
1614+ ( LocalNodeId ( 0 ) , {
1615+ let mut node = Node :: new( Role :: Window ) ;
1616+ node. set_children( vec![ LocalNodeId ( 1 ) ] ) ;
1617+ node
1618+ } ) ,
1619+ ( LocalNodeId ( 1 ) , Node :: new( Role :: Button ) ) ,
1620+ ] ,
1621+ tree : Some ( Tree :: new ( LocalNodeId ( 0 ) ) ) ,
1622+ tree_id : TreeId :: ROOT ,
1623+ focus : LocalNodeId ( 0 ) ,
1624+ } ;
1625+ let tree = super :: Tree :: new ( update, false ) ;
1626+
1627+ let root = tree
1628+ . state ( )
1629+ . node_by_tree_local_id ( LocalNodeId ( 0 ) , TreeId :: ROOT )
1630+ . unwrap ( ) ;
1631+ assert_eq ! ( root. id( ) , node_id( 0 ) ) ;
1632+ assert_eq ! ( root. role( ) , Role :: Window ) ;
1633+
1634+ let child = tree
1635+ . state ( )
1636+ . node_by_tree_local_id ( LocalNodeId ( 1 ) , TreeId :: ROOT )
1637+ . unwrap ( ) ;
1638+ assert_eq ! ( child. id( ) , node_id( 1 ) ) ;
1639+ assert_eq ! ( child. role( ) , Role :: Button ) ;
1640+ }
1641+
1642+ #[ test]
1643+ fn node_by_tree_local_id_finds_subtree_node ( ) {
1644+ let update = TreeUpdate {
1645+ nodes : vec ! [
1646+ ( LocalNodeId ( 0 ) , {
1647+ let mut node = Node :: new( Role :: Window ) ;
1648+ node. set_children( vec![ LocalNodeId ( 1 ) ] ) ;
1649+ node
1650+ } ) ,
1651+ ( LocalNodeId ( 1 ) , {
1652+ let mut node = Node :: new( Role :: GenericContainer ) ;
1653+ node. set_tree_id( subtree_id( ) ) ;
1654+ node
1655+ } ) ,
1656+ ] ,
1657+ tree : Some ( Tree :: new ( LocalNodeId ( 0 ) ) ) ,
1658+ tree_id : TreeId :: ROOT ,
1659+ focus : LocalNodeId ( 0 ) ,
1660+ } ;
1661+ let mut tree = super :: Tree :: new ( update, false ) ;
1662+
1663+ let subtree_update = TreeUpdate {
1664+ nodes : vec ! [
1665+ ( LocalNodeId ( 0 ) , {
1666+ let mut node = Node :: new( Role :: Document ) ;
1667+ node. set_children( vec![ LocalNodeId ( 1 ) ] ) ;
1668+ node
1669+ } ) ,
1670+ ( LocalNodeId ( 1 ) , Node :: new( Role :: Paragraph ) ) ,
1671+ ] ,
1672+ tree : Some ( Tree :: new ( LocalNodeId ( 0 ) ) ) ,
1673+ tree_id : subtree_id ( ) ,
1674+ focus : LocalNodeId ( 0 ) ,
1675+ } ;
1676+ tree. update_and_process_changes ( subtree_update, & mut NoOpHandler ) ;
1677+
1678+ let sub_root = tree
1679+ . state ( )
1680+ . node_by_tree_local_id ( LocalNodeId ( 0 ) , subtree_id ( ) )
1681+ . unwrap ( ) ;
1682+ assert_eq ! ( sub_root. id( ) , subtree_node_id( 0 ) ) ;
1683+ assert_eq ! ( sub_root. role( ) , Role :: Document ) ;
1684+
1685+ let sub_child = tree
1686+ . state ( )
1687+ . node_by_tree_local_id ( LocalNodeId ( 1 ) , subtree_id ( ) )
1688+ . unwrap ( ) ;
1689+ assert_eq ! ( sub_child. id( ) , subtree_node_id( 1 ) ) ;
1690+ assert_eq ! ( sub_child. role( ) , Role :: Paragraph ) ;
1691+
1692+ let graft = tree
1693+ . state ( )
1694+ . node_by_tree_local_id ( LocalNodeId ( 1 ) , TreeId :: ROOT )
1695+ . unwrap ( ) ;
1696+ assert_eq ! ( graft. id( ) , node_id( 1 ) ) ;
1697+ assert_eq ! ( graft. role( ) , Role :: GenericContainer ) ;
1698+ }
1699+
1700+ #[ test]
1701+ fn node_by_tree_local_id_returns_none_for_unknown_tree_id ( ) {
1702+ let update = TreeUpdate {
1703+ nodes : vec ! [ ( LocalNodeId ( 0 ) , Node :: new( Role :: Window ) ) ] ,
1704+ tree : Some ( Tree :: new ( LocalNodeId ( 0 ) ) ) ,
1705+ tree_id : TreeId :: ROOT ,
1706+ focus : LocalNodeId ( 0 ) ,
1707+ } ;
1708+ let tree = super :: Tree :: new ( update, false ) ;
1709+
1710+ assert ! ( tree
1711+ . state( )
1712+ . node_by_tree_local_id( LocalNodeId ( 0 ) , subtree_id( ) )
1713+ . is_none( ) ) ;
1714+ }
1715+
1716+ #[ test]
1717+ fn node_by_tree_local_id_returns_none_for_unknown_local_id ( ) {
1718+ let update = TreeUpdate {
1719+ nodes : vec ! [ ( LocalNodeId ( 0 ) , Node :: new( Role :: Window ) ) ] ,
1720+ tree : Some ( Tree :: new ( LocalNodeId ( 0 ) ) ) ,
1721+ tree_id : TreeId :: ROOT ,
1722+ focus : LocalNodeId ( 0 ) ,
1723+ } ;
1724+ let tree = super :: Tree :: new ( update, false ) ;
1725+
1726+ assert ! ( tree
1727+ . state( )
1728+ . node_by_tree_local_id( LocalNodeId ( 999 ) , TreeId :: ROOT )
1729+ . is_none( ) ) ;
1730+ }
1731+
15651732 #[ test]
15661733 fn subtree_root_parent_is_graft_when_graft_exists_first ( ) {
15671734 let update = TreeUpdate {
0 commit comments