Module layout

Module layout 

Source
Expand description

Phase E.4.B Phase 4 — pure layout-tree helpers (Rust port of layoutTree.ts). Pure layout-tree helper functions for the srv E.4.B reducer.

Phase 4 of docs/specs/srv-phase-e4b-formal-spec-2026-05-03.md. Ports the 11 pure-ish action handlers from frontend/layout/lib/layoutTree.ts to Rust. These functions take &mut LayoutNode (the tree root) and operation params; they have no I/O and no side effects. The reducer arms (Phase 5) will call these.

Test oracle: the 30 tests in frontend/layout/tests/layoutTree.test.ts (shipped in PR #686) — the Rust implementations must produce identical state transitions for identical inputs.

Structs§

InsertCandidate 🔒
Candidate for insertion location, collected during tree traversal.

Enums§

LayoutError

Constants§

DEFAULT_MAX_CHILDREN
Maximum children before insert_node’s heuristic descends. Mirrors frontend/layout/lib/layoutTree.ts::DEFAULT_MAX_CHILDREN.
DEFAULT_NODE_SIZE
Default flex size for newly-inserted nodes. Mirrors frontend/layout/lib/types.ts::DefaultNodeSize.

Functions§

clear_tree_node
Clear the tree root. Callers set the Option<LayoutNode> to None. This function exists only to be referenced in the test helper pattern; actual clearing in the reducer just sets root = None.
collect_insert_candidates 🔒
delete_node
Remove the node with the given id from the tree. Returns Ok(()) on success, or Err(NodeNotFound) if node_id is not in the tree. Callers are responsible for clearing focused_node_id if needed (spec §7.1). Collapses single-child parents.
delete_recursive 🔒
Recursive delete. Returns true when the node was found and removed, false when not found.
ensure_group_node 🔒
If node is a leaf (has data), promote it to a group by wrapping its data in an intermediate child. Mirrors TypeScript addIntermediateNode in frontend/layout/lib/layoutTree.ts.
find_next_insert_location 🔒
Find the best insertion location using the TypeScript scoring heuristic (Math.pow(depth, index + maxChildren)). Collects all candidates, then sorts by ascending score. Mirrors findNextInsertLocation in frontend/layout/lib/layoutNode.ts.
find_node_by_id
Find a node by id (immutable).
find_node_by_id_mut
Find a node by id (mutable).
find_parent_id 🔒
insert_node
Insert node using the TypeScript scoring heuristic (up to DEFAULT_MAX_CHILDREN per node before descending). If the target location is a leaf, it is promoted to a group first via ensure_group_node. Mirrors insertNode / addChildAt in frontend/layout/lib/layoutTree.ts.
insert_node_at_index
Insert node at the location identified by index_arr — an ordered sequence of child indices (e.g. [0, 2] = root.children[0].children at index 3). The node is inserted AFTER the position identified by the last index.
move_node
Move the node identified by node_id to be the child at index under the node identified by new_parent_id. Resets the moved node’s size to DEFAULT_NODE_SIZE unless it stays under the same parent.
remove_node_from_parent 🔒
replace_node
Replace the node at target_id with new_node, preserving the target’s size. If target is root, replaces root-in-place (caller’s Option<LayoutNode> doesn’t change reference — the fields are updated on the root node).
resize_nodes
Apply resize operations. Validates all sizes first (0.0–100.0 range); if any is invalid, returns an error WITHOUT applying any ops (atomically rejected — matches the frontend’s early-return semantic from PR #686).
reverse_flex_direction 🔒
Reverse a flex direction (Row ↔ Column). Mirrors frontend/layout/lib/layoutNode.ts::reverseFlexDirection.
split_horizontal
Horizontal split: insert new_node before/after target_id.
split_impl 🔒
split_vertical
Vertical split: insert new_node before/after target_id.
swap_nodes
Swap two nodes (by id). Their sizes travel with them (swap positions but preserve the size each node had). Neither can be the root.