Expand description
phase-421 W5 — the schema-driven serialization strategy (RFC-0088 D7).
A provider that declares impl = "schema" in its nros-serdes.toml writes
ONE implementation and gets every message, with no codegen plugin and no
generated code per type. This module is the machinery that makes that true:
the walk over crate::schema::Field lives here, once, and a provider
supplies only the primitive encode/decode operations of its own wire.
§The signature RFC-0088 D7 sketched cannot be implemented
D7 wrote:
fn serialize(msg: *const u8, schema: &'static [Field], out: &mut [u8]) -> …That takes the HOST STRUCT as a pointer and reads fields at Field::offset.
Measured against the schemas codegen actually emits, it stops at the first
variable-length field, and it does so for three independent reasons:
- A
Stringfield’s host type isheapless::String<N>and the schema does not carryN.nros generate-rustemitsFieldType::String— the IDL type — for a member whose Rust storage is a fixed-capacity buffer.BoundedString(n)is the IDL bound, not the host capacity, and the two are different numbers. heapless::String/heapless::Vecarerepr(Rust). Their field order and padding are unspecified, so “the length is at offset 0” is not a fact this crate is allowed to assume.Field::offsetis well defined —offset_of!works on arepr(Rust)struct — but it only gets you to the START of the container, and the container’s own interior is opaque.- A nested type’s SIZE is not in the schema.
crate::schema::NestedTypecarriestype_nameandfields; striding anArray(N, Nested(..))or a sequence of structs needssize_ofof the element, and the largestoffsetin arepr(Rust)child does not determine it.
Extending the schema to carry host layout would change what codegen must
emit for every committed generated message, which is a different change from
this one. So the pivot moves: the value access a schema-driven provider has
today is the CDR byte stream, which nano-ros already produces for every
message from generated code. impl = "schema" is therefore a TRANSCODER
strategy in v1 — CDR in, foreign wire out, and back — and that is precisely
why the walk belongs here rather than in each provider.
The cost is the one D7 already accepted: schema-driven is slower than the
per-type serializer we emit for CDR, and impl = "codegen" is the answer
when someone hits the wall.
§What the walk does not cover
FieldType::WString / FieldType::BoundedWString reach
SchemaError::Unsupported, because crate::cdr::CdrReader has no
wide-string primitive to read them WITH — there is no read_wstring, in
either direction. No message in packages/interfaces/* uses one, so this is
a hole in the CDR codec that the schema walk inherits rather than one it
introduces.
Enums§
- Schema
Error - What can go wrong in a schema-driven encode or decode.
Traits§
- Schema
Serializer - A serialization format implemented once, by walking the schema (RFC-0088 D7).
- Schema
Sink - The encode half of a schema-driven format: the walk pushes typed values in, the implementor writes its wire.
- Schema
Source - The decode half: the walk pulls typed values out, in schema order.
Functions§
- decode_
to_ cdr - Walk
schema, pulling each value fromsourceand writing CDR. - encode_
from_ cdr - Walk
schema, reading CDR and pushing each value intosink.