Skip to main content

Module read

Module read 

Source
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 0x05 for 5;
  • an indefinite length, on a string, a list or a map;
  • a float, a half float included, and the undefined simple value;
  • a simple value below 32 written in the one-byte form — f8 14 is a second spelling of f4, 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§

CborError
Why a block is not a value in this data model.

Constants§

MAX_DEPTH
How deep a value may nest before it is refused.

Functions§

decode
Decodes one block into the data model.
integer 🔒
An argument as the data model’s one number type.
shortest 🔒
Whether an argument is written in the narrowest form that holds it.
simple 🔒
The three simple values the profile has, and the refusal of everything else.