Skip to main content

Module lenient_bytes

Module lenient_bytes 

Expand description

Wire-shape-tolerant deserialization for schema Bytes fields — see cratestack#783.

A schema Bytes field generates as a plain Vec<u8>, and Vec<u8>’s Deserialize is serde’s blanket Vec<T> impl: a visitor with visit_seq and nothing else. Over CBOR that accepts only an array of integers (0x84 01 02 03 04) and hard-errors on a CBOR byte string (0x44 01020304, RFC 8949 major type 2) with unexpected type bytes … expected array — the shape every other CBOR producer emits for binary data, and the shape @cratestack/cbor now writes for a JS Uint8Array/ArrayBuffer.

LenientBytes accepts both. visit_bytes/visit_byte_buf cover the byte-string form, visit_seq keeps the integer-array form working unchanged — which matters twice over: it is what every already-deployed client (Rust, Dart, and any TypeScript caller doing the Array.from(bytes) workaround) sends today, and it is the only shape JSON can express, so the application/json transport is unaffected.

Inbound only. Nothing here changes what a generated Serialize emits: a Bytes field still goes out as an array of integers on both transports and in all three client languages. Flipping the outbound shape to a byte string is a genuine wire break for every existing decoder (the Dart client’s cratestackAsValueList, the TypeScript client’s number[]), so it is deliberately not bundled here.

The deserialize_* wrappers exist one per generated field shape rather than as a single generic function because #[serde(deserialize_with = "…")] names a concrete function whose return type must match the field’s type exactly, and crate::shared::bytes_serde in cratestack-macros picks between them from the field’s arity and whether it is patch-wrapped. See that module for the mapping.

Structs§

LenientBytes
Vec<u8> newtype whose Deserialize accepts a byte string or a sequence of integers. See the module docs.

Functions§

deserialize_bytes
A required Bytes field — Vec<u8>.
deserialize_bytes_list
A list-arity Bytes field — Vec<Vec<u8>>. Each element independently accepts either shape.
deserialize_double_option_bytes
A patch-wrapped nullable Bytes field — Option<Option<Vec<u8>>>. The Bytes counterpart of crate::patch::deserialize_double_option (which can’t be reused: its T: Deserialize bound resolves to Vec<u8>’s strict blanket impl, the exact thing this module works around). Same contract — the outer Some records “this key was present”, so it must be paired with #[serde(default, …)].
deserialize_optional_bytes
A nullable Bytes field, or a patch-wrapped required one — Option<Vec<u8>>. Pair with #[serde(default, …)]: a custom deserialize_with opts the field out of serde-derive’s implicit “missing Option<T> field defaults to None” (see crate::patch).
deserialize_optional_bytes_list
A patch-wrapped list-arity Bytes field — Option<Vec<Vec<u8>>>. Pair with #[serde(default, …)], per deserialize_optional_bytes.