Expand description
Format registry – read/write/check a crate::document::Doc by format
name at runtime, plus register your own format plugins. Ported from
~/dev/omnist/omnist/registry.py (issue #31; see also the TypeScript
port’s registry.ts for the same architecture-freedom call made there).
Python’s registry is a plain dict[str, Format] of arbitrary callables –
genuine runtime plugin registration, exercised by
tests/test_canonical.py::TestRegistry: a caller can register_format
an arbitrary (name, read, write, check?) tuple at runtime and every
Doc-level API that takes a format name (from_format/to_format/
check_format) transparently picks it up. A closed enum dispatch (the
omnist-cli Fmt enum’s approach, or a match over the five builtins)
can’t express “register a new format at runtime under an arbitrary
name,” so this module reaches for the same dynamic-dispatch idiom Rust
uses in place of Python’s first-class functions: Arc<dyn Fn(...) + Send + Sync> trait objects, keyed by name in an IndexMap behind an
RwLock inside a OnceLock (this crate’s only piece of global mutable
state). Arc (not Box) so get_format can hand back an owned,
independently usable Format without holding the registry lock across
the caller’s use of it – mirroring Python’s _LOCK-guarded dict lookup,
which also releases the lock before the caller touches the returned
Format.
§Uniform signatures across five differently-shaped codecs
crate::formats::json::write_json takes an extra indent: Option< usize> the other three format writers don’t, and crate::oml’s
read_oml/write_oml operate on crate::document::RawNode rather
than Doc directly (see oml.rs’s own module doc on why). The
ReadFn/WriteFn the registry stores are Doc-in/Doc-out with no
format-specific options, matching Python’s registry entries as actually
invoked from this port’s zero-arg call sites (Python’s Doc.to_format
forwards **o through, but nothing in the Python test suite or
docs/api.md exercises that with the builtins, so this port keeps the
simpler no-options signature and documents the gap here rather than
silently reproducing untested surface). The five builtins are registered
as thin wrapper closures around the existing per-format functions with
their default options (indent: None, strict: false, no report
requested for writers; Doc::from_raw/to_raw bridging OML’s RawNode
shape) – get_format("json").read/.write are not literally
read_json/write_json (Rust can’t express “the same fn item” through
an Arc<dyn Fn> the way Python’s is can point at the same function
object), but they call straight through with no other logic, matching
Python’s actual invariant in spirit: no behavior is added or changed at
the registry boundary.
§OML’s check_oml
Rust’s port had no check_oml before this issue – OML is lossless for
every Doc (see oml.rs’s module doc: “no adjustment ever needed”), so
nothing needed to call it. Python’s check_oml exists purely to satisfy
the registry Format tuple’s fourth slot and always returns an empty
WriteReport; this issue adds the same trivial function to oml.rs for
the same reason (used only via the "oml" registry entry’s check).
Structs§
- Format
- A registered format: a name plus
read/writecallables and an optionalcheck. Mirrors Python’sFormatNamedTuple(name, read, write, check); a plugin registered withFormat::newalone has nocheck, andcrate::document::Doc::check_formaterrors cleanly (not a panic) if invoked on it – matchingtest_plugin_without_check_raises_on_check_format.
Functions§
- formats
- The names of all registered formats, sorted.
- get_
format - The registered
Formatforname. AnOmnistError::Formatif unknown, naming every currently-registered format name, sorted – mirrors Python’sget_format’sf"unknown format {name!r}; registered: {known}"message. Unlike Python, there is no"(none)"fallback for an empty registry:register_formatonly ever adds entries and the five builtins always register on first access (seebuiltins), so the registry can never actually be empty here – an untestable dead branch for that case was deliberately not carried over (playbook’s “unreachable dead code” gap classification), rather than kept under an unreachable coverage-ignore. - register_
format - Register (or replace) a format plugin, usable everywhere a format name is
accepted, including
crate::document::Doc::from_format/to_format/check_format.