Expand description
Reading a block back, which is a stricter job than writing one.
An encoder has to produce the one canonical form. A decoder has to refuse every other form, and that asymmetry is the whole of this file. Plain CBOR has five widths for the same integer, two lengths forms for every string, any order for a map’s keys and a tag space of thousands; all of it decodes to something. A decoder that accepted the lot would hand back values whose re-encoding is a different block with a different CID — which is to say it would let a peer hand this server two spellings of one record and get two identities for it.
So the rule here is: a block that does not re-encode to itself is not a
block. Every non-canonical form is an error rather than a value, and
decode’s own tests assert the round trip rather than trusting the
reading.
What this refuses that CBOR allows, in the order a parser meets it:
- an argument written wider than it needs —
0x18 0x05for 5; - an indefinite length, on a string, a list or a map;
- a float, a half float included, and the
undefinedsimple value; - a simple value below 32 written in the one-byte form —
f8 14is a second spelling off4, and a decoder that read it would re-encode the block to a different CID; - a tag other than 42, and a tag 42 over anything but an identity-prefixed CID;
- a map key that is not a text string, and a map whose keys are not in ascending DAG-CBOR order — which also rules out a duplicate key;
- a CID this crate cannot re-encode: see
Cid::from_bytes.
Nesting is bounded by MAX_DEPTH. A block arrives from a peer, and a
recursive descent parser over a few kilobytes of nested arrays is a stack
overflow — which aborts the process rather than unwinding, so it cannot be
caught anywhere upstream.
Structs§
- Header 🔒
- A major type and the argument that followed it.
- Reader 🔒
- A cursor over the block being read.
Enums§
- Cbor
Error - Why a block is not a value in this data model.
Constants§
- MAX_
DEPTH - How deep a value may nest before it is refused.