Skip to main content

latexml_core/sxml/
mod.rs

1//! Streaming XML substrate — the shared representation layer for fragmented
2//! (bounded-memory) conversion.
3//!
4//! The eager pipeline holds one whole-document DOM from Build to the final
5//! write, so peak RSS scales with document size (measured ~1.84 GB per MB of
6//! source on the 131 MB witness — `docs/performance/STREAMING_CORE_DESIGN_2026-07-29.md`).
7//! Fragmented mode bounds peak RSS by *fragment* size instead: closed subtrees
8//! are serialized to disk ("spilled") during Build and re-materialized one at a
9//! time for the later phases. This module is the substrate both halves stand
10//! on; it knows nothing about TeX or the schema:
11//!
12//! * [`SegmentStore`](crate::sxml::SegmentStore) — the on-disk spill area:
13//!   numbered segment files under a directory beside the destination (same
14//!   volume, so [`crate::watchdog::available_disk_bytes`] headroom checks
15//!   measure the right filesystem). Pass 1 writes parseable,
16//!   `_lxfragment`-wrapped segments; pass 2 replaces each with its processed,
17//!   splice-ready output text.
18//! * [`FragmentIndex`](crate::sxml::FragmentIndex) — the document-global facts
19//!   that must survive a spill as plain strings (never as node handles into a
20//!   freed DOM — the historical finalize-SIGSEGV class): spilled `xml:id`s and
21//!   which segment holds them, `label → id`, RDFa prefix declarations.
22//! * [`FragmentReader`](crate::sxml::FragmentReader) — a streaming iterator
23//!   over a segment (or any XML file): materializes ONE top-level subtree at a
24//!   time as an owned, mutable [`libxml::tree::Document`] via
25//!   `xmlTextReaderExpand`, while the rest of the file stays unparsed.
26//!
27//! Activation policy, spill-eligibility, and the placeholder-splice assembly
28//! live with their owners (`stomach`/`document`/`core_interface` for the core
29//! half, `latexml_post::stream_split` for the post half); this module only
30//! moves bytes and facts.
31
32mod fragment_index;
33mod fragment_reader;
34mod segment_store;
35
36pub use fragment_index::FragmentIndex;
37pub use fragment_reader::FragmentReader;
38pub use segment_store::{SegmentId, SegmentMeta, SegmentStore};