Expand description
Deterministic CBOR encoder and decoder following the
CBOR::Core
profile (draft-rundgren-cbor-core-25).
This crate works with CBOR as an owned data structure rather than as a serialization layer. Values can be constructed, inspected, modified, and round-tripped through their canonical byte encoding.
§Types
Value is the central type and a good starting point. It holds any
CBOR data item and provides constructors, accessors, encoding, and
decoding.
| Type | Role |
|---|---|
Value | Any CBOR data item. Start here. |
SimpleValue | CBOR simple value (null, true, false, 0-255). |
DataType | Classification of a value for type-level dispatch. |
Error | All errors produced by this crate. |
The following types are helpers that appear in From/Into bounds
and are rarely used directly:
| Type | Role |
|---|---|
Array | Wrapper around Vec<Value> accepted by array constructors. |
Map | Wrapper around BTreeMap<Value, Value> accepted by map constructors. |
Float | IEEE 754 float stored in shortest CBOR form (f16, f32, or f64). |
DateTime | Validated ISO 8601 UTC string for tag 0 construction. |
EpochTime | Validated numeric epoch time for tag 1 construction. |
§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
All encoding is deterministic: integers and floats use their shortest representation, and map keys are sorted in CBOR canonical order. The decoder rejects non-canonical input.
NaN values, including signaling NaNs and custom payloads, are preserved through encode/decode round-trips. Conversion between float widths uses bit-level manipulation to avoid hardware NaN canonicalization.
§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 |
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.
- 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. - 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 - Classification of a
Valuefor lightweight type checks. - Error
- Errors produced by this crate.
- IoError
- Error type for IO related operations.
- Value
- A single CBOR data item.