pub enum Dynamic {
Null,
Bool(bool),
U64(u64),
I64(i64),
F64(f64),
String(String),
Bytes(Vec<u8>),
Seq(Vec<Dynamic>),
Map(BTreeMap<String, Dynamic>),
Enum {
variant: String,
payload: Box<Dynamic>,
},
}Expand description
A postcard-decoded view of a stored record.
Dynamic is intentionally simple. It is the input shape every
Migrate::migrate impl receives; the migration code reads the
fields it cares about via Dynamic::get or
Dynamic::deserialize and constructs the target type by hand.
Variants§
Null
JSON-like null / Rust-like ().
Bool(bool)
Boolean.
U64(u64)
Unsigned 64-bit integer.
I64(i64)
Signed 64-bit integer.
F64(f64)
64-bit floating-point. NaN values do not compare equal to
themselves; equality for Dynamic::F64 follows the IEEE-754
definition (so Dynamic::F64(f64::NAN) != Dynamic::F64(f64::NAN)).
String(String)
UTF-8 string.
Bytes(Vec<u8>)
Raw byte sequence.
Seq(Vec<Dynamic>)
Ordered sequence of nested Dynamic values.
Map(BTreeMap<String, Dynamic>)
String-keyed map of nested Dynamic values. Iteration order
is the BTreeMap’s sorted-by-key order.
Enum
Tagged-enum value. variant carries the Rust variant name
(verbatim from
EnumVariantSchema::name);
payload carries the decoded inner value (a
Dynamic::Null for unit variants, a Dynamic::Map for
tuple / struct variants, or the inner type’s Dynamic for
newtype variants). Migration code distinguishes variants by
variant and pulls fields out of payload.
Implementations§
Source§impl Dynamic
impl Dynamic
Sourcepub fn from_tagged_bytes(bytes: &[u8]) -> Result<Self>
pub fn from_tagged_bytes(bytes: &[u8]) -> Result<Self>
Decode bytes as a tagged-Dynamic payload produced by
Dynamic::to_postcard_bytes.
This is not the inverse of postcard::to_allocvec(&doc)
for an arbitrary Document — see the module-level docs.
Dynamic::deserialize round-trips through native postcard
when the wire shapes match.
§Errors
Error::Codecif the underlying postcard decode fails.Error::Corruptionon an unknown tag, a length field that exceeds the input, or a tree depth or node count beyond the defense-in-depth bounds.
Sourcepub fn from_postcard_bytes(bytes: &[u8], schema: &DynamicSchema) -> Result<Self>
pub fn from_postcard_bytes(bytes: &[u8], schema: &DynamicSchema) -> Result<Self>
Decode a native-postcard payload according to schema.
This is the M10 migration entry point: given the on-disk
bytes of an older record + a DynamicSchema describing
that older type’s shape, the walker produces a structured
Dynamic view that a Migrate::migrate
impl can read fields out of.
Walks the byte stream iteratively with an explicit
Vec<Frame> stack per power-of-ten Rule 1. Depth is bounded
by MAX_SCHEMA_DEPTH.
§Errors
Error::SchemaDepthExceededif the schema is deeper thanMAX_SCHEMA_DEPTH.Error::SchemaTypeMismatchif the bytes do not match the schema (truncation, non-UTF-8 string, non-0|1bool, etc.).Error::Corruptionon a varint that overflowsu64.
Sourcepub fn to_postcard_bytes(&self) -> Result<Vec<u8>>
pub fn to_postcard_bytes(&self) -> Result<Vec<u8>>
Encode self as a tagged-Dynamic payload.
§Errors
Error::Codecif the underlying postcard encode fails.
Sourcepub fn get(&self, field: &str) -> Option<&Dynamic>
pub fn get(&self, field: &str) -> Option<&Dynamic>
Look up field in a Dynamic::Map. Returns None for any
non-map variant, mirroring JSON’s “missing field” semantics.
Sourcepub fn get_str(&self, field: &str) -> Result<&str>
pub fn get_str(&self, field: &str) -> Result<&str>
Typed accessor for String fields. Errors if field is
missing OR carries a non-string value — distinguishes
“absent” from “wrong shape” so migration code can fail
loudly on a schema mismatch.
§Errors
Error::SchemaTypeMismatchwithexpected = "String"when the field is absent OR the field’s variant is notDynamic::String.
Sourcepub fn set<S, V>(&mut self, field: S, value: V)
pub fn set<S, V>(&mut self, field: S, value: V)
Set field to value in a Dynamic::Map.
On a non-map variant the method replaces self with a fresh
Map containing only (field, value). This matches the
“best-effort upgrade” shape Migrate impls typically need
when adding a brand-new field to a previously-scalar payload.
Accepts any impl Into<Dynamic> — call sites can write
doc.set("tier", "gold") or doc.set("count", 42u64)
without explicitly wrapping the value.
Sourcepub fn remove(&mut self, field: &str) -> Result<Option<Dynamic>>
pub fn remove(&mut self, field: &str) -> Result<Option<Dynamic>>
Remove field from a Dynamic::Map.
Map-only. On a non-Map variant returns
Error::DynamicPathNotMap. On a Map, returns the removed
value (or None if absent) — distinguishes “field absent”
from “called remove on the wrong shape”.
Typical use is inside a Migrate::migrate body when the
new-version type has dropped a field that the old-version
payload carried:
fn migrate(mut doc: Dynamic, _from: u32) -> Result<Self> {
doc.remove("deprecated_field")?; // drop, do not roundtrip
doc.set("new_field", "default");
doc.deserialize()
}§Errors
Error::DynamicPathNotMapifselfis not aMap.
Sourcepub fn enum_variant(&self) -> Option<&str>
pub fn enum_variant(&self) -> Option<&str>
If self is a Dynamic::Enum, return the variant name;
otherwise None. Mirrors Dynamic::get’s “missing field”
semantics: a non-Enum value silently returns None rather
than erroring.
Sourcepub fn enum_payload(&self) -> Option<&Dynamic>
pub fn enum_payload(&self) -> Option<&Dynamic>
If self is a Dynamic::Enum, return the decoded payload;
otherwise None. Pairs with Dynamic::enum_variant in a
Migrate::migrate body — match on the variant name, then
pull fields out of the payload.
Sourcepub fn deserialize<T: DeserializeOwned>(&self) -> Result<T>
pub fn deserialize<T: DeserializeOwned>(&self) -> Result<T>
Round-trip self through native postcard and deserialise as
T. Useful for types whose postcard wire shape happens to
match the Dynamic shape (primarily other map-shaped types
or types that are themselves Dynamic-valued).
Caveat. Dynamic’s Serialize impl emits a serde Map
for its Map variant. postcard encodes a Rust struct as a
field-ordered tuple (no key names) — so deserialising a
Dynamic::Map payload as a struct will read the map’s
length as the first field. For struct migration the
recommended pattern is per-field extraction via
Dynamic::get; see the dynamic_migration_shape test in
this module for the worked example.
§Errors
Error::Codecon any postcard error.