Expand description
Deterministic CBOR encoder and decoder following the
CBOR::Core
profile (draft-rundgren-cbor-core-25).
The central type is an owned Value. It can be constructed,
inspected, modified in place, encoded to bytes, and decoded back.
The API follows CBOR’s own shape, so tagged values, simple values,
and arbitrary map keys stay directly reachable without a detour
through a schema.
§Types
Value is the owned representation of any CBOR data item. It handles
construction, inspection, encoding, and decoding, and is what most code
works with directly.
Array,Map,Float,DateTime,EpochTime, andSimpleValueappear inFrom/Intobounds forValueand are rarely constructed by hand.DataTypereports a value’s kind for type-based dispatch.ValueKeyis the key type for maps.DecodeOptionsconfigures the decoder andFormatselects binary, hex, or diagnostic input.SequenceDecoderandSequenceReaderiterate over CBOR sequences;SequenceWriteris their write-side counterpart.ErrorandResultcover in-memory decoding;IoErrorandIoResultcoverio::Readsources.
§Quick start
use cbor_core::{Value, array, map};
// Build a value
let value = map! {
1 => "hello",
2 => array![10, 20, 30],
};
// Encode to bytes and decode back
let bytes = value.encode();
let decoded = Value::decode(&bytes).unwrap();
assert_eq!(value, decoded);
// Access inner data
let greeting = decoded[1].as_str().unwrap();
assert_eq!(greeting, "hello");
// Round-trip through diagnostic notation
let text = format!("{value:?}");
let parsed: Value = text.parse().unwrap();
assert_eq!(value, parsed);§Diagnostic notation
Value implements FromStr, so any CBOR value can
be written as text and parsed with str::parse. This is often the
shortest way to build a literal value in a test, a fixture, or an
example, and it avoids manual Value::from chains for nested data.
The grammar is Section 2.3.6 of the CBOR::Core draft. Examples:
use cbor_core::Value;
// Integers in any base, with `_` as a digit separator
let v: Value = "0xff_ff_00_00".parse().unwrap();
assert_eq!(v, Value::from(0xff_ff_00_00_u32));
// Arbitrary precision: parsed as tag 2 / tag 3 big integers
let big: Value = "18446744073709551616".parse().unwrap();
assert_eq!(big, Value::from(u64::MAX as u128 + 1));
// Floats, including explicit bit patterns for NaN payloads
let f: Value = "1.5e2".parse().unwrap();
assert_eq!(f, Value::from(150.0));
let nan: Value = "float'7f800001'".parse().unwrap();
assert_eq!(nan.encode(), vec![0xfa, 0x7f, 0x80, 0x00, 0x01]);
// Byte strings: hex, base64, ASCII, or embedded CBOR
assert_eq!("h'48656c6c6f'".parse::<Value>().unwrap(), Value::from(b"Hello".to_vec()));
assert_eq!("b64'SGVsbG8'".parse::<Value>().unwrap(), Value::from(b"Hello".to_vec()));
assert_eq!("'Hello'".parse::<Value>().unwrap(), Value::from(b"Hello".to_vec()));
// << ... >> wraps a CBOR sequence into a byte string
assert_eq!(
"<< 1, 2, 3 >>".parse::<Value>().unwrap(),
Value::ByteString(vec![0x01, 0x02, 0x03]),
);Nested structures are written directly, and maps may appear in any order. The parser sorts keys and rejects duplicates:
use cbor_core::Value;
let cert: Value = r#"{
/ CWT-style claims, written out of canonical order /
"iss": "https://issuer.example",
"sub": "user-42",
"iat": 1700000000,
"cnf": {
"kty": "OKP",
"crv": "Ed25519",
"x": h'd75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a'
},
"scope": ["read", "write"]
}"#.parse().unwrap();
assert_eq!(cert["sub"].as_str().unwrap(), "user-42");
assert_eq!(cert["cnf"]["crv"].as_str().unwrap(), "Ed25519");Supported grammar elements: integers (decimal, 0x, 0o, 0b, with
_ separators), arbitrary-precision integers, floats (decimal,
scientific, NaN, Infinity, float'<hex>'), text strings with
JSON-style escapes and surrogate pairs, byte strings (h'...',
b64'...', '...', <<...>>), arrays, maps, tagged values N(...),
simple(N), true, false, null, single-line # ... comments, and
block / ... / comments.
The parser accepts non-canonical input (for example unsorted maps and
non-shortest numbers), normalizes it, and produces a canonical Value.
Round-tripping format!("{v:?}").parse::<Value>() always yields the
original value.
§Encoding rules
Encoding is deterministic: integers and floats use their shortest form, and map keys are sorted in canonical order. The decoder rejects input that deviates.
NaN payloads, including signaling NaNs, survive round-trips bit-for-bit. Float-width conversions go through bit patterns to avoid hardware canonicalization.
§Sequences
A CBOR sequence (RFC 8742) is zero or more items concatenated
without framing. The library reads and writes sequences in all
three formats selected by Format.
On the read side, DecodeOptions::sequence_decoder wraps a byte
slice and yields a SequenceDecoder with
Item = Result<Value, Error>.
DecodeOptions::sequence_reader wraps any io::Read and yields
a SequenceReader with Item = Result<Value, IoError>.
In binary and hex, items sit back-to-back. In diagnostic notation, items are comma-separated, with an optional trailing comma.
On the write side, SequenceWriter::new takes an io::Write
and a Format, to select binary, hex, or diagnostic output.
Three methods feed items in:
| Method | Input |
|---|---|
write_item | &Value |
write_items | IntoIterator<Item = &Value> |
write_pairs | IntoIterator<Item = (&Value, &Value)> |
write_pairs emits each key and value as two consecutive items,
matching the shape of &BTreeMap::iter(), so a map held in a
Value streams straight into a sequence.
Array and Map bridge between a sequence and an owned
collection:
| Constructor | Input | Behavior |
|---|---|---|
Array::from_sequence | IntoIterator<Item = Value> | collects into an array |
Array::try_from_sequence | IntoIterator<Item = Result<Value, E>> | short-circuits on the first error |
Map::from_pairs | iterator of (Value, Value) | last write wins on duplicate keys |
Map::try_from_pairs | iterator of (Value, Value) | rejects duplicates with Error::NonDeterministic |
Map::from_sequence | IntoIterator<Item = Value> | alternating key/value; strict canonical order |
Map::try_from_sequence | IntoIterator<Item = Result<Value, E>> | fallible-input form of from_sequence |
The try_* forms take fallible iterators directly, so a
SequenceDecoder or SequenceReader can feed an Array or
Map without an intermediate Vec.
Map::try_from_sequence uses the bound E: From<Error>, which
covers both iterators because IoError already has
From<Error>.
use cbor_core::{Array, DecodeOptions, Format, SequenceWriter, Value};
let items = [Value::from(1), Value::from("hi"), Value::from(true)];
let mut buf = Vec::new();
SequenceWriter::new(&mut buf, Format::Binary)
.write_items(items.iter())
.unwrap();
let array = Array::try_from_sequence(
DecodeOptions::new().sequence_decoder(&buf),
).unwrap();
assert_eq!(array.get_ref().as_slice(), &items);§Optional features
| Feature | Adds |
|---|---|
serde | Serialize/Deserialize for Value, serde::to_value, serde::from_value |
chrono | Conversions between chrono::DateTime and DateTime/EpochTime/Value |
time | Conversions between time::UtcDateTime/OffsetDateTime and DateTime/EpochTime/Value |
jiff | Conversions between jiff::Timestamp/Zoned and DateTime/EpochTime/Value |
half | From/TryFrom between Float/Value and half::f16 |
num-bigint | From/TryFrom between Value and num_bigint::BigInt/BigUint |
crypto-bigint | From/TryFrom between Value and crypto_bigint::Uint/Int/NonZero |
rug | From/TryFrom between Value and rug::Integer |
Modules§
Macros§
- array
- Construct a CBOR array from a list of expressions.
- map
- Construct a CBOR map from a list of
key => valuepairs.
Structs§
- Array
- Conversion helper for
Value::array. - Date
Time - Helper for validated date/time string construction.
- Decode
Options - Configuration for CBOR decoding.
- Epoch
Time - Helper for validated epoch time construction.
- Float
- A floating-point value stored in its shortest CBOR encoding form.
- Map
- Conversion helper for
Value::map. - Sequence
Decoder - Iterator over a CBOR sequence stored in a byte slice.
- Sequence
Reader - Iterator over a CBOR sequence pulled from an
io::Readsource. - Sequence
Writer - Streaming writer for CBOR sequences in binary, hex, or diagnostic notation.
- Simple
Value - A CBOR simple value (major type 7, values 0-23 and 32-255).
- Value
Key - A key for looking up elements in
Valuearrays and maps.
Enums§
- Data
Type - Kind of a
Value. - Error
- Errors produced by this crate.
- Format
- Format for CBOR decoding or encoding.
- IoError
- Error type for IO related operations.
- Value
- A single CBOR data item.