1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
//! 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 fn`s ([`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.
use crateScalar;
use crate;
use crate;
use crateMAX_INT_DIGITS;
use Parser;
use Scanner;
use ;
/// Parse OML source into a canonical [`RawNode`] (edge-list or leaf).
///
/// Supports the full OML-Core grammar, plus OML-Extended raw-string (`'...'`)
/// and triple-quoted multiline-string (`"""..."""`) spellings -- see the
/// module doc comment.
/// Render a canonical [`RawNode`] as OML-Core source, pretty-printed with
/// `indent` spaces per nesting level.
///
/// OML is lossless for every Document: there's never an adjustment to
/// report, so there's no `strict=`/report machinery -- writing always
/// succeeds, unless the input itself nests deeper than
/// [`crate::document::MAX_DEPTH`] (see the module doc comment on the depth
/// guard).
/// Single-line ("compact") rendering: edges joined by `"; "`, no
/// newlines/padding. Mirrors Python's `write_oml(..., indent=None)`. Both
/// forms round-trip through [`read_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's `check_oml`, which is exactly `return
/// WriteReport()`. Every other builtin format has a `check_*` function
/// already; this is the OML counterpart, needed so the `"oml"` registry
/// entry has a `check` callable like the other four.
/// Marker type implementing [`crate::formats::Codec`] for OML -- adapts
/// [`read_oml`]/[`write_oml`]/[`check_oml`] to the registry's uniform
/// `Doc`-in/`Doc`-out shape, exactly as `registry::builtins` did by hand
/// before this issue: `read` bridges `read_oml`'s [`RawNode`] result
/// through [`crate::document::Doc::from_raw`], and `write` bridges the
/// other way through `Doc::to_raw` before calling `write_oml` with its
/// documented default indent (2).
pub ;