Skip to content

Commit

Permalink
feat: Make the consumer crate no-std
Browse files Browse the repository at this point in the history
  • Loading branch information
mwcampbell committed Oct 22, 2024
1 parent 2fa0d3f commit ff679ae
Show file tree
Hide file tree
Showing 7 changed files with 63 additions and 32 deletions.
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion consumer/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@ rust-version.workspace = true

[dependencies]
accesskit = { version = "0.16.3", path = "../common" }
immutable-chunkmap = "2.0.5"
immutable-chunkmap = "2.0.6"
5 changes: 3 additions & 2 deletions consumer/src/iterators.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE.chromium file.

use std::iter::FusedIterator;
use core::iter::FusedIterator;

use accesskit::NodeId;

Expand Down Expand Up @@ -435,7 +435,7 @@ impl<'a, Filter: Fn(&Node) -> FilterResult> FusedIterator for FilteredChildren<'
pub(crate) enum LabelledBy<'a, Filter: Fn(&Node) -> FilterResult> {
FromDescendants(FilteredChildren<'a, Filter>),
Explicit {
ids: std::slice::Iter<'a, NodeId>,
ids: core::slice::Iter<'a, NodeId>,
tree_state: &'a TreeState,
},
}
Expand Down Expand Up @@ -477,6 +477,7 @@ impl<'a, Filter: Fn(&Node) -> FilterResult> FusedIterator for LabelledBy<'a, Fil
mod tests {
use crate::tests::*;
use accesskit::NodeId;
use alloc::vec::Vec;

#[test]
fn following_siblings() {
Expand Down
5 changes: 5 additions & 0 deletions consumer/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
// the LICENSE-APACHE file) or the MIT license (found in
// the LICENSE-MIT file), at your option.

#![no_std]

extern crate alloc;

pub(crate) mod tree;
pub use tree::{ChangeHandler as TreeChangeHandler, State as TreeState, Tree};

Expand All @@ -23,6 +27,7 @@ pub use text::{
#[cfg(test)]
mod tests {
use accesskit::{Affine, NodeBuilder, NodeId, Rect, Role, Tree, TreeUpdate, Vec2};
use alloc::vec;

use crate::FilterResult;

Expand Down
9 changes: 7 additions & 2 deletions consumer/src/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,16 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE.chromium file.

use std::{iter::FusedIterator, sync::Arc};

use accesskit::{
Action, Affine, DefaultActionVerb, Live, Node as NodeData, NodeId, Orientation, Point, Rect,
Role, TextSelection, Toggled,
};
use alloc::{
string::{String, ToString},
sync::Arc,
vec::Vec,
};
use core::iter::FusedIterator;

use crate::filters::FilterResult;
use crate::iterators::{
Expand Down Expand Up @@ -674,6 +678,7 @@ impl<'a> Node<'a> {
#[cfg(test)]
mod tests {
use accesskit::{NodeBuilder, NodeId, Point, Rect, Role, Tree, TreeUpdate};
use alloc::vec;

use crate::tests::*;

Expand Down
6 changes: 4 additions & 2 deletions consumer/src/text.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
use accesskit::{
NodeId, Point, Rect, Role, TextDirection, TextPosition as WeakPosition, TextSelection,
};
use std::{cmp::Ordering, iter::FusedIterator};
use alloc::{string::String, vec::Vec};
use core::{cmp::Ordering, iter::FusedIterator};

use crate::{FilterResult, Node, TreeState};

Expand Down Expand Up @@ -498,7 +499,7 @@ pub struct Range<'a> {
impl<'a> Range<'a> {
fn new(node: Node<'a>, mut start: InnerPosition<'a>, mut end: InnerPosition<'a>) -> Self {
if start.comparable(&node) > end.comparable(&node) {
std::mem::swap(&mut start, &mut end);
core::mem::swap(&mut start, &mut end);
}
Self { node, start, end }
}
Expand Down Expand Up @@ -1099,6 +1100,7 @@ impl<'a> Node<'a> {
#[cfg(test)]
mod tests {
use accesskit::{NodeId, Point, Rect, TextSelection};
use alloc::vec;

// This is based on an actual tree produced by egui.
fn main_multiline_tree(selection: Option<TextSelection>) -> crate::Tree {
Expand Down
64 changes: 41 additions & 23 deletions consumer/src/tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,15 @@
// the LICENSE-MIT file), at your option.

use accesskit::{Node as NodeData, NodeId, Tree as TreeData, TreeUpdate};
use immutable_chunkmap::map::MapM as ChunkMap;
use std::{
collections::{HashMap, HashSet},
use alloc::{
collections::{BTreeMap, BTreeSet},
format,
string::String,
sync::Arc,
vec,
vec::Vec,
};
use immutable_chunkmap::map::MapM as ChunkMap;

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

Expand All @@ -22,9 +26,9 @@ pub struct State {

#[derive(Default)]
struct InternalChanges {
added_node_ids: HashSet<NodeId>,
updated_node_ids: HashSet<NodeId>,
removed_node_ids: HashSet<NodeId>,
added_node_ids: BTreeSet<NodeId>,
updated_node_ids: BTreeSet<NodeId>,
removed_node_ids: BTreeSet<NodeId>,
}

impl State {
Expand All @@ -43,7 +47,7 @@ impl State {
is_host_focused: bool,
mut changes: Option<&mut InternalChanges>,
) {
let mut orphans = HashSet::new();
let mut orphans = BTreeSet::new();

if let Some(tree) = update.tree {
if tree.root != self.data.root {
Expand All @@ -53,8 +57,10 @@ impl State {
}

let root = self.data.root;
let mut pending_nodes: HashMap<NodeId, _> = HashMap::new();
let mut pending_children = HashMap::new();
let mut pending_nodes = BTreeMap::new();
let mut pending_node_count = 0usize;
let mut pending_children = BTreeMap::new();
let mut pending_child_count = 0usize;

fn add_node(
nodes: &mut ChunkMap<NodeId, NodeState>,
Expand All @@ -76,7 +82,7 @@ impl State {
for (node_id, node_data) in update.nodes {
orphans.remove(&node_id);

let mut seen_child_ids = HashSet::new();
let mut seen_child_ids = BTreeSet::new();
for (child_index, child_id) in node_data.children().iter().enumerate() {
if seen_child_ids.contains(child_id) {
panic!(
Expand All @@ -90,7 +96,10 @@ impl State {
if child_state.parent_and_index != Some(parent_and_index) {
child_state.parent_and_index = Some(parent_and_index);
}
} else if let Some(child_data) = pending_nodes.remove(child_id) {
} else if let Some(child_data) =
pending_nodes.get_mut(child_id).and_then(Option::take)
{
pending_node_count -= 1;
add_node(
&mut self.nodes,
&mut changes,
Expand All @@ -99,9 +108,10 @@ impl State {
child_data,
);
} else {
pending_children.insert(*child_id, parent_and_index);
pending_children.insert(*child_id, Some(parent_and_index));
pending_child_count += 1;
}
seen_child_ids.insert(child_id);
seen_child_ids.insert(*child_id);
}

if let Some(node_state) = self.nodes.get_mut_cow(&node_id) {
Expand All @@ -119,7 +129,10 @@ impl State {
changes.updated_node_ids.insert(node_id);
}
}
} else if let Some(parent_and_index) = pending_children.remove(&node_id) {
} else if let Some(parent_and_index) =
pending_children.get_mut(&node_id).and_then(Option::take)
{
pending_child_count -= 1;
add_node(
&mut self.nodes,
&mut changes,
Expand All @@ -130,29 +143,30 @@ impl State {
} else if node_id == root {
add_node(&mut self.nodes, &mut changes, None, node_id, node_data);
} else {
pending_nodes.insert(node_id, node_data);
pending_nodes.insert(node_id, Some(node_data));
pending_node_count += 1;
}
}

if !pending_nodes.is_empty() {
panic!("TreeUpdate includes {} nodes which are neither in the current tree nor a child of another node from the update: {}", pending_nodes.len(), short_node_list(pending_nodes.keys()));
if pending_node_count > 0 {
panic!("TreeUpdate includes {} nodes which are neither in the current tree nor a child of another node from the update: {}", pending_node_count, short_node_list(pending_nodes.into_iter().filter_map(|(key, value)| value.is_some().then_some(key))));
}
if !pending_children.is_empty() {
panic!("TreeUpdate's nodes include {} children ids which are neither in the current tree nor the id of another node from the update: {}", pending_children.len(), short_node_list(pending_children.keys()));
if pending_child_count > 0 {
panic!("TreeUpdate's nodes include {} children ids which are neither in the current tree nor the id of another node from the update: {}", pending_child_count, short_node_list(pending_children.into_iter().filter_map(|(key, value)| value.is_some().then_some(key))));
}

self.focus = update.focus;
self.is_host_focused = is_host_focused;

if !orphans.is_empty() {
let mut to_remove = HashSet::new();
let mut to_remove = Vec::new();

fn traverse_orphan(
nodes: &ChunkMap<NodeId, NodeState>,
to_remove: &mut HashSet<NodeId>,
to_remove: &mut Vec<NodeId>,
id: NodeId,
) {
to_remove.insert(id);
to_remove.push(id);
let node = nodes.get(&id).unwrap();
for child_id in node.data.children().iter() {
traverse_orphan(nodes, to_remove, *child_id);
Expand Down Expand Up @@ -363,11 +377,13 @@ impl Tree {
}
}

fn short_node_list<'a>(nodes: impl ExactSizeIterator<Item = &'a NodeId>) -> String {
fn short_node_list(nodes: impl Iterator<Item = NodeId>) -> String {
let nodes = nodes.collect::<Vec<_>>();
if nodes.len() > 10 {
format!(
"[{} ...]",
nodes
.into_iter()
.take(10)
.map(|id| format!("#{}", id.0))
.collect::<Vec<_>>()
Expand All @@ -377,6 +393,7 @@ fn short_node_list<'a>(nodes: impl ExactSizeIterator<Item = &'a NodeId>) -> Stri
format!(
"[{}]",
nodes
.into_iter()
.map(|id| format!("#{}", id.0))
.collect::<Vec<_>>()
.join(", "),
Expand All @@ -387,6 +404,7 @@ fn short_node_list<'a>(nodes: impl ExactSizeIterator<Item = &'a NodeId>) -> Stri
#[cfg(test)]
mod tests {
use accesskit::{NodeBuilder, NodeId, Role, Tree, TreeUpdate};
use alloc::vec;

#[test]
fn init_tree_with_root_node() {
Expand Down

0 comments on commit ff679ae

Please sign in to comment.