Skip to main content

Crate cbor_core

Crate cbor_core 

Source
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.

TypeRole
ValueAny CBOR data item. Start here.
SimpleValueCBOR simple value (null, true, false, 0-255).
DataTypeClassification of a value for type-level dispatch.
ErrorAll errors produced by this crate.

The following types are helpers that appear in From/Into bounds and are rarely used directly:

TypeRole
ArrayWrapper around Vec<Value> accepted by array constructors.
MapWrapper around BTreeMap<Value, Value> accepted by map constructors.
FloatIEEE 754 float stored in shortest CBOR form (f16, f32, or f64).
DateTimeValidated ISO 8601 UTC string for tag 0 construction.
EpochTimeValidated 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

FeatureAdds
serdeSerialize/Deserialize for Value, serde::to_value, serde::from_value
chronoConversions between chrono::DateTime and DateTime/EpochTime/Value
timeConversions between time::UtcDateTime/OffsetDateTime and DateTime/EpochTime/Value
halfFrom/TryFrom between Float/Value and half::f16
num-bigintFrom/TryFrom between Value and num_bigint::BigInt/BigUint
crypto-bigintFrom/TryFrom between Value and crypto_bigint::Uint/Int/NonZero
rugFrom/TryFrom between Value and rug::Integer

Modules§

serdeserde
Serde integration for CBOR Value.

Macros§

array
Construct a CBOR array from a list of expressions.
map
Construct a CBOR map from a list of key => value pairs.

Structs§

Array
Conversion helper for Value::array.
DateTime
Helper for validated date/time string construction.
EpochTime
Helper for validated epoch time construction.
Float
A floating-point value stored in its shortest CBOR encoding form.
Map
Conversion helper for Value::map.
SimpleValue
A CBOR simple value (major type 7, values 0-23 and 32-255).
ValueKey
A key for looking up elements in Value arrays and maps.

Enums§

DataType
Classification of a Value for lightweight type checks.
Error
Errors produced by this crate.
IoError
Error type for IO related operations.
Value
A single CBOR data item.

Type Aliases§

IoResult
Convenience alias for streaming CBOR operations.
Result
Convenience alias used throughout this crate.