Skip to content

Commit 9d78086

Browse files
authored
feat: Allow looking up nodes by LocalNodeId and TreeId (#707)
1 parent 85ca4ef commit 9d78086

1 file changed

Lines changed: 177 additions & 10 deletions

File tree

consumer/src/tree.rs

Lines changed: 177 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ struct TreeIndexMap {
2222
}
2323

2424
impl 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

Comments
 (0)