Skip to content

Commit a74dbfc

Browse files
authored
refactor!: Replace immutable-chunkmap with dual tree states (#495)
1 parent 70e0348 commit a74dbfc

File tree

4 files changed

+57
-58
lines changed

4 files changed

+57
-58
lines changed

Cargo.lock

Lines changed: 0 additions & 10 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

consumer/Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,3 @@ rust-version.workspace = true
1414
[dependencies]
1515
accesskit = { version = "0.18.0", path = "../common" }
1616
hashbrown = { version = "0.15", default-features = false, features = ["default-hasher"] }
17-
immutable-chunkmap = "2.0.6"

consumer/src/node.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ use accesskit::{
1414
};
1515
use alloc::{
1616
string::{String, ToString},
17-
sync::Arc,
1817
vec::Vec,
1918
};
2019
use core::{fmt, iter::FusedIterator};
@@ -32,7 +31,7 @@ pub(crate) struct ParentAndIndex(pub(crate) NodeId, pub(crate) usize);
3231
#[derive(Clone, Debug)]
3332
pub(crate) struct NodeState {
3433
pub(crate) parent_and_index: Option<ParentAndIndex>,
35-
pub(crate) data: Arc<NodeData>,
34+
pub(crate) data: NodeData,
3635
}
3736

3837
#[derive(Copy, Clone)]

consumer/src/tree.rs

Lines changed: 56 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,15 @@
44
// the LICENSE-MIT file), at your option.
55

66
use accesskit::{FrozenNode as NodeData, NodeId, Tree as TreeData, TreeUpdate};
7-
use alloc::{sync::Arc, vec};
7+
use alloc::vec;
88
use core::fmt;
99
use hashbrown::{HashMap, HashSet};
10-
use immutable_chunkmap::map::MapM as ChunkMap;
1110

1211
use crate::node::{Node, NodeState, ParentAndIndex};
1312

1413
#[derive(Clone, Debug)]
1514
pub struct State {
16-
pub(crate) nodes: ChunkMap<NodeId, NodeState>,
15+
pub(crate) nodes: HashMap<NodeId, NodeState>,
1716
pub(crate) data: TreeData,
1817
pub(crate) focus: NodeId,
1918
is_host_focused: bool,
@@ -28,10 +27,10 @@ struct InternalChanges {
2827

2928
impl State {
3029
fn validate_global(&self) {
31-
if self.nodes.get_key(&self.data.root).is_none() {
30+
if !self.nodes.contains_key(&self.data.root) {
3231
panic!("Root id #{} is not in the node list", self.data.root.0);
3332
}
34-
if self.nodes.get_key(&self.focus).is_none() {
33+
if !self.nodes.contains_key(&self.focus) {
3534
panic!("Focused id #{} is not in the node list", self.focus.0);
3635
}
3736
}
@@ -56,17 +55,17 @@ impl State {
5655
let mut pending_children = HashMap::new();
5756

5857
fn add_node(
59-
nodes: &mut ChunkMap<NodeId, NodeState>,
58+
nodes: &mut HashMap<NodeId, NodeState>,
6059
changes: &mut Option<&mut InternalChanges>,
6160
parent_and_index: Option<ParentAndIndex>,
6261
id: NodeId,
6362
data: NodeData,
6463
) {
6564
let state = NodeState {
6665
parent_and_index,
67-
data: Arc::new(data),
66+
data,
6867
};
69-
nodes.insert_cow(id, state);
68+
nodes.insert(id, state);
7069
if let Some(changes) = changes {
7170
changes.added_node_ids.insert(id);
7271
}
@@ -87,9 +86,12 @@ impl State {
8786
}
8887
unreachable.remove(child_id);
8988
let parent_and_index = ParentAndIndex(node_id, child_index);
90-
if let Some(child_state) = self.nodes.get_mut_cow(child_id) {
89+
if let Some(child_state) = self.nodes.get_mut(child_id) {
9190
if child_state.parent_and_index != Some(parent_and_index) {
9291
child_state.parent_and_index = Some(parent_and_index);
92+
if let Some(changes) = &mut changes {
93+
changes.updated_node_ids.insert(*child_id);
94+
}
9395
}
9496
} else if let Some(child_data) = pending_nodes.remove(child_id) {
9597
add_node(
@@ -105,7 +107,7 @@ impl State {
105107
seen_child_ids.insert(*child_id);
106108
}
107109

108-
if let Some(node_state) = self.nodes.get_mut_cow(&node_id) {
110+
if let Some(node_state) = self.nodes.get_mut(&node_id) {
109111
if node_id == root {
110112
node_state.parent_and_index = None;
111113
}
@@ -114,8 +116,8 @@ impl State {
114116
unreachable.insert(*child_id);
115117
}
116118
}
117-
if *node_state.data != node_data {
118-
node_state.data = Arc::new(node_data);
119+
if node_state.data != node_data {
120+
node_state.data.clone_from(&node_data);
119121
if let Some(changes) = &mut changes {
120122
changes.updated_node_ids.insert(node_id);
121123
}
@@ -147,14 +149,14 @@ impl State {
147149

148150
if !unreachable.is_empty() {
149151
fn traverse_unreachable(
150-
nodes: &mut ChunkMap<NodeId, NodeState>,
152+
nodes: &mut HashMap<NodeId, NodeState>,
151153
changes: &mut Option<&mut InternalChanges>,
152154
id: NodeId,
153155
) {
154156
if let Some(changes) = changes {
155157
changes.removed_node_ids.insert(id);
156158
}
157-
let node = nodes.remove_cow(&id).unwrap();
159+
let node = nodes.remove(&id).unwrap();
158160
for child_id in node.data.children().iter() {
159161
traverse_unreachable(nodes, changes, *child_id);
160162
}
@@ -240,6 +242,7 @@ pub trait ChangeHandler {
240242
#[derive(Debug)]
241243
pub struct Tree {
242244
state: State,
245+
next_state: State,
243246
}
244247

245248
impl Tree {
@@ -248,17 +251,16 @@ impl Tree {
248251
panic!("Tried to initialize the accessibility tree without a root tree. TreeUpdate::tree must be Some.");
249252
};
250253
let mut state = State {
251-
nodes: ChunkMap::new(),
254+
nodes: HashMap::new(),
252255
data: tree,
253256
focus: initial_state.focus,
254257
is_host_focused,
255258
};
256259
state.update(initial_state, is_host_focused, None);
257-
Self { state }
258-
}
259-
260-
pub fn update(&mut self, update: TreeUpdate) {
261-
self.state.update(update, self.state.is_host_focused, None);
260+
Self {
261+
next_state: state.clone(),
262+
state,
263+
}
262264
}
263265

264266
pub fn update_and_process_changes(
@@ -267,14 +269,9 @@ impl Tree {
267269
handler: &mut impl ChangeHandler,
268270
) {
269271
let mut changes = InternalChanges::default();
270-
let old_state = self.state.clone();
271-
self.state
272+
self.next_state
272273
.update(update, self.state.is_host_focused, Some(&mut changes));
273-
self.process_changes(old_state, changes, handler);
274-
}
275-
276-
pub fn update_host_focus_state(&mut self, is_host_focused: bool) {
277-
self.state.update_host_focus_state(is_host_focused, None);
274+
self.process_changes(changes, handler);
278275
}
279276

280277
pub fn update_host_focus_state_and_process_changes(
@@ -283,55 +280,69 @@ impl Tree {
283280
handler: &mut impl ChangeHandler,
284281
) {
285282
let mut changes = InternalChanges::default();
286-
let old_state = self.state.clone();
287-
self.state
283+
self.next_state
288284
.update_host_focus_state(is_host_focused, Some(&mut changes));
289-
self.process_changes(old_state, changes, handler);
285+
self.process_changes(changes, handler);
290286
}
291287

292-
fn process_changes(
293-
&self,
294-
old_state: State,
295-
changes: InternalChanges,
296-
handler: &mut impl ChangeHandler,
297-
) {
288+
fn process_changes(&mut self, changes: InternalChanges, handler: &mut impl ChangeHandler) {
298289
for id in &changes.added_node_ids {
299-
let node = self.state.node_by_id(*id).unwrap();
290+
let node = self.next_state.node_by_id(*id).unwrap();
300291
handler.node_added(&node);
301292
}
302293
for id in &changes.updated_node_ids {
303-
let old_node = old_state.node_by_id(*id).unwrap();
304-
let new_node = self.state.node_by_id(*id).unwrap();
294+
let old_node = self.state.node_by_id(*id).unwrap();
295+
let new_node = self.next_state.node_by_id(*id).unwrap();
305296
handler.node_updated(&old_node, &new_node);
306297
}
307-
if old_state.focus_id() != self.state.focus_id() {
308-
let old_node = old_state.focus();
298+
if self.state.focus_id() != self.next_state.focus_id() {
299+
let old_node = self.state.focus();
309300
if let Some(old_node) = &old_node {
310301
let id = old_node.id();
311302
if !changes.updated_node_ids.contains(&id)
312303
&& !changes.removed_node_ids.contains(&id)
313304
{
314-
if let Some(old_node_new_version) = self.state.node_by_id(id) {
305+
if let Some(old_node_new_version) = self.next_state.node_by_id(id) {
315306
handler.node_updated(old_node, &old_node_new_version);
316307
}
317308
}
318309
}
319-
let new_node = self.state.focus();
310+
let new_node = self.next_state.focus();
320311
if let Some(new_node) = &new_node {
321312
let id = new_node.id();
322313
if !changes.added_node_ids.contains(&id) && !changes.updated_node_ids.contains(&id)
323314
{
324-
if let Some(new_node_old_version) = old_state.node_by_id(id) {
315+
if let Some(new_node_old_version) = self.state.node_by_id(id) {
325316
handler.node_updated(&new_node_old_version, new_node);
326317
}
327318
}
328319
}
329320
handler.focus_moved(old_node.as_ref(), new_node.as_ref());
330321
}
331322
for id in &changes.removed_node_ids {
332-
let node = old_state.node_by_id(*id).unwrap();
323+
let node = self.state.node_by_id(*id).unwrap();
333324
handler.node_removed(&node);
334325
}
326+
for id in changes.added_node_ids {
327+
self.state
328+
.nodes
329+
.insert(id, self.next_state.nodes.get(&id).unwrap().clone());
330+
}
331+
for id in changes.updated_node_ids {
332+
self.state
333+
.nodes
334+
.get_mut(&id)
335+
.unwrap()
336+
.clone_from(self.next_state.nodes.get(&id).unwrap());
337+
}
338+
for id in changes.removed_node_ids {
339+
self.state.nodes.remove(&id);
340+
}
341+
if self.state.data != self.next_state.data {
342+
self.state.data.clone_from(&self.next_state.data);
343+
}
344+
self.state.focus = self.next_state.focus;
345+
self.state.is_host_focused = self.next_state.is_host_focused;
335346
}
336347

337348
pub fn state(&self) -> &State {

0 commit comments

Comments
 (0)