Expand description
OML (Omnist Markup Language) – the native codec for the Document model.
Ported from ~/dev/omnist/omnist/oml.py (issue #10). OML is omnist’s own
serialization format: every Document – every ordered, possibly-repeated,
possibly-interleaved edge list, and all seven scalar kinds (string,
integer, number, boolean, date, time, datetime) plus null –
round-trips through OML exactly, with no adjustment ever needed (unlike
JSON/YAML/TOML/XML).
This module implements the OML-Core grammar in full for both
read_oml and write_oml, plus the OML-Extended raw-string
('...', E2) and triple-quoted multiline-string ("""...""", E3)
spellings on read only – write_oml only ever emits OML-Core
double-quoted strings, matching the Python reference.
§Layout (issue #53)
scanner tokenizes source text, parser consumes those tokens into
a RawNode, and writer renders a RawNode back to OML-Core
source. This top-level module keeps the module doc overview, the four
pub fns (read_oml, write_oml, write_oml_compact,
check_oml), and the Codec adapter –
nothing about crate::oml::* paths changed by the split.
§Architecture (per issue #1/#10, “architecture freedom”)
Python’s reader is a single-pass scanner built around one compiled
“master” regex, deferring line/col computation and scalar-value
construction until actually needed – a Python-performance-specific
design (see the module’s PR #168 for the profile that motivated it), not
a behavioral requirement. This port uses a straightforward hand-written
recursive-descent scanner/parser over byte-indexed &str instead: idiomatic
Rust, and there’s no equivalent hot-path reason to defer decoding here.
Observable behavior (parse results, round-trips, error content) matches
the Python reference; exact error wording does not need to.
§Node representation
crate::document::RawNode – not crate::document::Value – is the
type this codec reads into and writes from. Value::Object’s IndexMap
can’t hold a repeated key, so it only represents “repeated label” as a
contiguous run (an array value under one key); OML must round-trip
arbitrary interleaving of repeated labels losslessly (its whole
reason for existing – “no adjustment ever needed”), which only
RawNode’s literal edge list can hold exactly.
§Depth guard (omnist-ts#37 / omnist-ts#70)
write_oml takes a plain, unchecked crate::document::RawNode –
exactly like Python’s write_oml(node), which accepts any hand-built
canonical node, not necessarily one that passed through a depth-checked
builder. So the writer calls the shared
crate::document::check_write_depth guard itself, at every nesting
level, rather than assuming its input already got checked somewhere
upstream – the exact bug class omnist-ts#37/#70 were: a writer (or a
second writer) that skipped this because some builder happened to
guard depth already.
Functions§
- check_
oml - Report what writing OML would adjust, without producing output. Added
for issue #31 (the format registry): OML is lossless for every
Document(see this module’s doc comment), so there is never anything to report – mirrors Python’scheck_oml, which is exactlyreturn WriteReport(). Every other builtin format has acheck_*function already; this is the OML counterpart, needed so the"oml"registry entry has acheckcallable like the other four. - read_
oml - Parse OML source into a canonical
RawNode(edge-list or leaf). - write_
oml - Render a canonical
RawNodeas OML-Core source, pretty-printed withindentspaces per nesting level. - write_
oml_ compact - Single-line (“compact”) rendering: edges joined by
"; ", no newlines/padding. Mirrors Python’swrite_oml(..., indent=None). Both forms round-trip throughread_oml.