smix-screen
Accessibility tree types for iOS-Simulator automation — A11yNode,
Rect, Bounds, Role, ElementSummary, ScreenDescription — with
inlined visibility primitives that approach single-cycle latency on
M-series machines.
Zero-allocation arithmetic, #[inline] on the hot path, criterion bench
medians available below for reference. The visibility math is the same
semantics maestro and Apple's XCUITest enforce (any non-empty frame
intersection with the viewport, zero-width / zero-height bounds
short-circuit to false).
Quickstart
use ;
let node = A11yNode ;
let viewport = Rect ;
let tree = A11yNode ;
assert!;
assert_eq!;
let summary = summarize_node;
assert_eq!;
let summaries = collect_visible_summaries;
assert_eq!; // root + button
Performance (criterion bench medians on M-series macOS)
| Operation | TS V8 baseline | smix-screen Rust |
Speedup |
|---|---|---|---|
is_visible_enough (in-view) |
21.2 ns | 0.996 ns | 21× |
is_visible_enough (zero-bounds early reject) |
20.5 ns | 0.449 ns | 46× |
is_visible_enough (unknown-root conservative pass) |
20.6 ns | 0.584 ns | 35× |
is_visible_enough (offscreen) |
20.7 ns | 0.805 ns | 26× |
visible_area (intersection arithmetic) |
20.9 ns | 1.112 ns | 19× |
dfs_collect 100-node composite |
788 ns | 233 ns | 3.4× |
Numbers reproducible via cargo bench --bench visibility -p smix-screen.
When to reach for this
| Use case | Pick |
|---|---|
Need typed A11yNode matching Apple's XCUIElement attribute set |
smix-screen |
| Need to filter "visible enough" candidates on a hot path | smix-screen |
Want the same visibility semantics as maestro / XCUITest .isHittable |
smix-screen |
| Need a full DOM/HTML accessibility tree (browser context) | use a browser-focused crate; this is iOS-shaped |
| Need physical device a11y tree | this is sim-shaped (camelCase wire fields match xcrun simctl io outputs) |
Wire compatibility
JSON serialization uses serde(rename_all = "camelCase") matching the
iOS-Simulator runner conventions: rawType, placeholderValue,
hasFocus. children: Vec<A11yNode> is recursive; terminal nodes
may omit the field (serde default = "...").
The Role enum mirrors XCUIElement.ElementType literals (29 variants)
with a stable camelCase wire name accessor (Role::Button.as_str() →
"button").
Scope
- ✅ Pure types + visibility primitives
- ✅
#[inline]+ zero-allocation hot path - ✅ camelCase JSON wire matches the iOS sim runner format
- ✅
ScreenDescription+collect_visible_summariesfor DFS-pre-order visible-element projection - ❌ No tree fetch (use
smix-runner-clientfor the HTTP IPC) - ❌ No selector parsing (use
smix-selector) - ❌ No resolver / spatial filter logic (use
smix-selector-resolver)
License
Dual-licensed under either:
at your option.