Skip to main content

Module dom

Module dom 

Source
Expand description

Bumpalo-backed, libxml2-shaped DOM.

This is the v2 tree representation that replaces the per-node-malloc design in [crate::node]. It’s not wired into the parser yet — that happens in Milestone 2. Until then, the rest of the codebase keeps using the existing [crate::node] types unchanged.

§Design

  • One arena per document. A bumpalo::Bump owns all node, attribute, namespace, and string allocations. Per-node alloc cost drops to a pointer bump; drop is free per node — the whole arena is freed at once.

  • libxml2-shaped nodes. A single Node struct (not a Rust enum) with a NodeKind tag and inline fields for every variant. Children form a doubly-linked list via first_child/last_child on the parent and next_sibling/prev_sibling + parent on each child. Attributes form their own doubly-linked list on the element. Field offsets and semantics mirror xmlNode so a future extern "C" shim can expose the same memory to libxml2 callers verbatim.

  • Cell-of-references for links. All sibling/child/parent pointers are Cell<Option<&'doc Node<'doc>>>. This is the standard idiomatic pattern for graph-shaped data in an arena: you get mutation without RefCell overhead and without raw pointers in the public API.

  • Strings borrowed where possible. Names and text contents are &'doc str. When the parser can borrow from the source slice directly it does; otherwise it allocates a copy in the arena. No Arc<str> per name.

§The self-referential Document wrapper

Document owns a Bump and holds a root pointer (&Node) into that same Bump. That’s a self-referential struct, which safe Rust doesn’t express directly. The arena nodes have stable addresses (bumpalo never relocates allocations), so the references are sound in principle. We encode it with one contained unsafe block in Document::root, audited by:

  1. The Bump is stored in an Arc<Bump> — heap-allocated, never moved while any clone of the Arc lives. C-ABI consumers (sup-xml-compat) share a single thread-local arena across every document, so cross-doc node grafts (libxml2 consumers like lxml moving nodes between documents) are safe by construction — node memory outlives any individual doc.
  2. The root pointer is built from &Bump::alloc(...) of the same Bump, so the lifetime is genuinely 'self (as in: tied to the Document).
  3. The Document’s public methods hand out references with a borrow of &self, which the borrow checker treats as 'self-bounded. Outside those methods, no 'doc reference can escape.

See Document for the API.

Structs§

AttrIter
Iterator over an element’s attributes.
Attribute
An attribute on an element. Belongs to a doubly-linked list rooted at Node::first_attribute / Node::last_attribute on its owning element.
ChildIter
Iterator over a node’s children.
Document
Document owns a Bump and a pointer to the root Node inside that Bump. The struct is self-referential and the unsafety is contained — see the module-level docs for the safety argument.
DocumentBuilder
Constructs a Document one node at a time. The parser uses this internally; consumers building trees by hand use the same.
HtmlDoctype
Captured DOCTYPE content from an HTML document. Stored verbatim; HTML5 does not validate against DTDs, but the public/system identifiers are surfaced for tools that want to introspect them (e.g. detecting XHTML vs HTML5 input).
HtmlMeta
HTML-specific document metadata. Set when the document came from parse_html_*; None for XML documents.
Namespace
A namespace binding (prefix → href). Lifetime-bound to the document’s arena.
Node
A node in the XML tree. One struct for every kind; fields are used per-kind.
UnparsedEntity
An owned XML document with an arena-allocated tree.

Enums§

NodeKind
Discriminant for Node::kind.
NsDeclIter
Iterator yielded by Node::ns_declarations. Each item is (prefix, href) where prefix is None for the default namespace declaration. The variant in use depends on the build feature flags — callers should treat it as opaque.
QuirksMode
HTML5 quirks-mode flag set from the DOCTYPE. Only meaningful for HTML documents; XML documents always carry None for Document::html_metadata.