serde feature is enabled by default.
Main exports
Data conversion belongs to
differens-tiers::tree_from_value; core consumers do
not need to depend on the parsers if they construct their own trees.
Build trees
TreeBuilder::push(NodeSpec) returns a Result<NodeId, BuildError>. Children must precede their parent, in source order, with contiguous postorder ranges. Shared children, invalid byte ranges, zero source lines, and disconnected forests are rejected. finish(root) returns Result<Arc<Tree>, BuildError>.
Tree::node(NodeId) borrows immutable metadata. root_ref() on Arc<Tree> returns an owned NodeRef; it holds the tree alive and exposes children() and parent(). An ID belongs to one tree. Spans use UTF-8 byte offsets; lines are one-based.
NodeSpec::match_key: Option<String> supplies an internal identity hint for same-named containers, such as go::basicWriter for an overloaded Go method. Tree::match_key(id) and NodeRef::match_key() expose it. Keys occupy a sparse tree-level map and distinguish named-container paths. Each hinted node and its descendants match within the same (kind, key) scope; nested hints override their ancestor’s scope. Labels remain editable within a scope, so method renames still work. This prevents identical bodies from being matched into an unrelated receiver’s helper. Keys do not change labels, legacy JSON, hashes, or exact content equality. Detachment and flat snapshots preserve the applicable keys.
Compare
DiffResult has changes, node_count, and optional fallback. A tree larger than max_nodes returns empty changes and Some(Fallback::Lines). The default core limit is usize::MAX; callers choose their budget.
EditAction variants are Insert, Delete, Update, and Move. Each owns node references and a nearest-first Vec<NodeContext>. Updates carry UpdateDetail::Renamed { from, to } or ValueChanged { from, to }. A scalar type transition qualifies the values with their types. Missing values remain None.
Actions are ordered updates, moves, deletions, insertions. Subtree additions/removals absorb descendant edits; sibling reorders use a longest increasing subsequence, anchoring named containers whose relative order stays unchanged before aligning anonymous siblings between them. This is a deterministic heuristic edit script, not a guarantee of a globally minimal tree edit distance.
Hashes and serialization
hash_text(&str) -> u64 preserves the legacy 53-bit folded FNV hash over UTF-16 code units. Content and structure fingerprints select candidates; full topology and field checks verify them. trees_equal(&NodeRef, &NodeRef) uses iterative exact equality.
Node serialization preserves nested legacy JSON. NodeRef::shallow() emits metadata with empty children while retaining the owning tree internally. Flat ownership and iterative traversal avoid recursive stack growth for deep construction, equality, matching, JSON encoding, and drop.
Adapters using TreeBuilder::with_source or set_legacy_source keep native UTF-8 byte spans while serializing legacy UTF-16 code-unit spans. Detached nodes and flat snapshots retain only the coordinate deltas needed by their node boundaries. A small candidate retains only the coordinate metadata needed for its subtree, even after a large Unicode prefix. Tree::auxiliary_heap_bytes() exposes a conservative retained-size estimate for offset and identity maps.
Matching options
DiffResult::node_count is the sum of both input tree sizes. A fallback result
has no actions; it does not mean that the sources are equal. The caller must
compare lines, or use diff_with_tier to handle that step.
Node metadata
NodeRef keeps the tree alive through shared ownership. Child IDs do not own
nested nodes, so dropping a deeply nested tree does not recurse through one heap
allocation per node. Use NodeSpec as builder input; finished node metadata is
immutable.
Action fields
context is a nearest-ancestor-first vector of NodeContext { kind, label }.
Use action.node(), action.context(), and action.action_type() when you do
not need to match every variant. Rename details contain from and to strings;
value details retain optional values. JSON uses camelCase names for move fields.
Compare typed value trees
differens-tiers
dependency. The installation guide
shows path dependencies for an unpublished checkout.