aws/internal/codec/cbor
Minimal CBOR (RFC 8949) codec for the rpcv2Cbor protocol.
AWS’s rpcv2Cbor wire form is the canonical / deterministic CBOR subset: definite-length arrays + maps, no tags, no indefinite-length items, sort keys lexicographically when encoding maps. The decoder is more permissive — it accepts indefinite-length items too because real services have been observed shipping them.
Major types this implementation covers:
- 0 unsigned int — 1/2/3/5/9-byte head encoding
- 1 negative int — 1/2/3/5/9-byte head
- 2 byte string — length-prefixed
- 3 text string — length-prefixed UTF-8
- 4 array — definite-length on encode, both on decode
- 5 map — definite-length on encode, both on decode
- 7 simple values + floats — false/true/null/float64
Not yet covered: tags (major type 6), undefined (simple 23),
half-float (0xF9), 32-bit float (0xFA). Half- and 32-bit floats
would surface only from CBOR senders explicitly downcasting; the
AWS rpcv2Cbor services we’ve seen always send float64. Tags are
reserved for date-time / bignum encodings the rpcv2Cbor spec
excludes from request/response bodies.
Types
pub type Value {
CInt(value: Int)
CFloat(value: Float)
CBool(value: Bool)
CNull
CString(value: String)
CBytes(value: BitArray)
CList(items: List(Value))
CMap(entries: List(#(Value, Value)))
}
Constructors
-
CInt(value: Int) -
CFloat(value: Float) -
CBool(value: Bool) -
CNull -
CString(value: String) -
CBytes(value: BitArray) -
CList(items: List(Value)) -
Map values are stored as a
Listrather than aDictso the encoder can preserve insertion order — rpcv2Cbor only cares about lexicographic key order on encode, which the encoder enforces, but on decode the original order is observable for downstream consumers (e.g. for diffing against a deterministic reference).
Values
pub fn decode(
bytes: BitArray,
) -> Result(#(Value, BitArray), String)
Decode a CBOR byte stream into a Value. Returns the leftover
bytes on success so callers can decode multiple items from one
buffer; rpcv2Cbor request bodies are single items, so most
callers can just drop the leftover.
pub fn decode_value(bytes: BitArray) -> Result(Value, String)
Convenience helper for callers that just want the decoded value and don’t care about the trailing bytes (the common rpcv2Cbor request/response body case).
pub fn get_field(map: Value, key: String) -> option.Option(Value)
option.None (None) when looking up a key that’s not present
in a CMap. Used by hand-written decoders that pluck specific
fields out of a CBOR-decoded map.