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 encode-side counterpart, configured withEncodeFormat.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::from(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 is zero or more items concatenated
without framing. The read side is configured with Format; the
encode side uses EncodeFormat, which adds output-only variants
(DiagnosticPretty) and accepts
any Format through impl Into<EncodeFormat>.
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 encode side, SequenceWriter::new takes an io::Write
and an impl Into<EncodeFormat>, so a Format or an
EncodeFormat can be passed directly. Items are fed in through:
write_itemfor a single&Value.write_itemsfor anyIntoIterator<Item = &Value>.write_pairsfor anIntoIterator<Item = (&Value, &Value)>, which emits each key and value as two consecutive items. This matches the shape of&BTreeMap::iter(), so a map held in aValuestreams straight into a sequence.
Array and Map bridge between a sequence and an owned
collection:
Array::from_sequencecollects anIntoIterator<Item = Value>into an array.Array::try_from_sequencetakes a fallible iterator (Item = Result<Value, E>) and short-circuits on the first error.Map::from_pairsconsumes(Value, Value)pairs with last-write-wins on duplicate keys.Map::try_from_pairsrejects duplicates withError::NonDeterministic.Map::from_sequencetakes anIntoIterator<Item = Value>of alternating key and value items in strict canonical order.Map::try_from_sequenceis the fallible-input form offrom_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, Value::serialized, Value::deserialized |
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 |
Re-exports§
pub use serde::SerdeError;serde
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. - Encode
Format - Format for CBOR output produced by
SequenceWriter. - 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.