Skip to main content

Module materialize

Module materialize 

Source
Expand description

Schema-directed deserialization: make a freshly-read RawNode conform to a Schema, or report every reason it doesn’t.

Ported from ~/dev/omnist/omnist/deserialize.py (issue #14). Readers hand back text-shaped values: JSON/YAML/TOML have no date/time type, so a temporal field arrives as an ISO-8601 string; a whole-number float may need to become an int (or vice versa) to match what the schema declares. materialize walks the node together with the schema, upgrading each leaf only when the conversion is value-exact (1.0 -> 1 for an integer field, 1 -> 1.0 for a number field – see the module’s scalar-upgrade table below) and checking every record’s shape (closed fields, cardinality) in the same pass – not a second top-down walk delegating to crate::schema::Schema::validate afterward. That would mean re-walking the same tree twice with different traversal code for no reason: materialize already knows, at every node, exactly which field/type the schema expects there, so upgrading and shape-checking happen together in one pass, matching the Python reference’s stated rationale.

§No native temporal Scalar variant

crate::document::Scalar has no date/time/datetime variant (see document.rs’s module doc) – every value this port ever materializes is Null/Bool/Int/Float/Str. So unlike the Python reference (which actually constructs a datetime.date/time/datetime object), “upgrading” a temporal field here can only ever mean “is this string shaped like, and a semantically valid, ISO date/time/datetime” – it stays a Str either way. That check is exactly crate::schema::is_iso_date/is_iso_time/is_iso_datetime, reused here rather than reimplemented – the exact “validate and materialize must share one strict parser” pitfall the porting playbook calls out, and the same functions crate::schema::matches_kind already uses.

§Scalar upgrade table (value-exact only)

field kindaccepts as-isupgrades
stringStr(none)
booleanBool(none)
integerIntFloat with a zero fractional part
numberFloatInt (always promoted to Float, matching the Python reference’s float(value))
date/time/datetimeStr shaped per the shared temporal check(none – see above)

null is accepted only when the field’s Scalar is nullable, regardless of kind.

§No strict= switch

There’s no separate strict/non-strict mode: materialize takes schema: Option<&Schema>None is the well-defined “opt out of validation entirely” case (the node is returned exactly as read, untouched), matching the Python reference’s schema=None convention at the reader call sites.

§The any type

An Any-typed field passes its node through completely untouched – no shape check, no scalar upgrade – mirroring Python’s _materialize_type: if isinstance(d, AnyType): return node.

Functions§

materialize
A copy of node with leaf values upgraded to match schema, guaranteed to conform to it – or every reason it can’t, collected into one MaterializeError (never just the first problem found).