pub enum Value {
SimpleValue(SimpleValue),
Unsigned(u64),
Negative(u64),
Float(Float),
ByteString(Vec<u8>),
TextString(String),
Array(Vec<Value>),
Map(BTreeMap<Value, Value>),
Tag(u64, Box<Value>),
}Expand description
A single CBOR data item.
Value covers all CBOR major types: integers, floats, byte and text
strings, arrays, maps, tagged values, and simple values (null, booleans).
It encodes deterministically and decodes only canonical input.
§Creating values
Rust primitives convert via From:
use cbor_core::Value;
let n = Value::from(42);
let s = Value::from("hello");
let b = Value::from(true);For arrays and maps the array! and map! macros are convenient:
use cbor_core::{Value, array, map};
let a = array![1, 2, 3];
let m = map! { "x" => 10, "y" => 20 };Arrays and maps can also be built from standard Rust collections.
Slices, Vecs, fixed-size arrays, BTreeMaps, HashMaps, and
slices of key-value pairs all convert automatically:
use cbor_core::Value;
use std::collections::HashMap;
// Array from a slice
let a = Value::array([1, 2, 3].as_slice());
// Map from a HashMap
let mut hm = HashMap::new();
hm.insert(1, 2);
let m = Value::map(&hm);
// Map from key-value pairs
let m = Value::map([("x", 10), ("y", 20)]);Use () to create empty arrays or maps without spelling out a type:
use cbor_core::Value;
let empty_array = Value::array(());
let empty_map = Value::map(());
assert_eq!(empty_array.as_array().unwrap().len(), 0);
assert_eq!(empty_map.as_map().unwrap().len(), 0);Named constructors are available for cases where From is ambiguous:
| Constructor | Builds |
|---|---|
Value::null() | Null simple value |
Value::simple_value(v) | Arbitrary simple value |
Value::float(v) | Float in shortest CBOR form |
Value::array(v) | Array from slice, Vec, or fixed-size array |
Value::map(v) | Map from BTreeMap, HashMap, slice of pairs, etc. |
Value::tag(n, v) | Tagged value |
§Encoding and decoding
use cbor_core::Value;
let original = Value::from(-1000);
let bytes = original.encode();
let decoded = Value::decode(&bytes).unwrap();
assert_eq!(original, decoded);For streaming use, write_to and
read_from operate on any io::Write / io::Read.
§Accessors
Accessor methods extract or borrow the inner data of each variant.
All return Result<T>, yielding Err(Error::IncompatibleType) on a
type mismatch. The naming follows Rust conventions:
| Prefix | Meaning | Returns |
|---|---|---|
as_* | Borrow inner data | &T or &mut T (with _mut) |
to_* | Convert or narrow | Owned Copy type (u8, f32, …) |
into_* | Consume self, extract | Owned T |
| no prefix | Trivial property | Copy scalar |
§Simple values
In CBOR, booleans and null are not distinct types but specific simple
values: false is 20, true is 21, null is 22. This means a
boolean value is always also a simple value. to_bool
provides typed access to true/false, while
to_simple_value works on any simple value
including booleans and null.
| Method | Returns | Notes |
|---|---|---|
to_simple_value | Result<u8> | Raw simple value number |
to_bool | Result<bool> | Only for true/false |
use cbor_core::Value;
let v = Value::from(true);
assert_eq!(v.to_bool().unwrap(), true);
assert_eq!(v.to_simple_value().unwrap(), 21); // CBOR true = simple(21)
// null is also a simple value
let n = Value::null();
assert!(n.to_bool().is_err()); // not a boolean
assert_eq!(n.to_simple_value().unwrap(), 22); // but is simple(22)§Integers
CBOR has effectively four integer types (unsigned or negative, and normal or big integer) with different internal representations. This is handled transparently by the API.
The to_* accessors perform checked
narrowing into any Rust integer type, returning Err(Overflow) if
the value does not fit, or Err(NegativeUnsigned) when extracting a
negative value into an unsigned type.
use cbor_core::Value;
let v = Value::from(1000);
assert_eq!(v.to_u32().unwrap(), 1000);
assert_eq!(v.to_i64().unwrap(), 1000);
assert!(v.to_u8().is_err()); // overflow
let neg = Value::from(-5);
assert_eq!(neg.to_i8().unwrap(), -5);
assert!(neg.to_u32().is_err()); // negative unsigned§Floats
Floats are stored internally in their shortest CBOR encoding (f16,
f32, or f64). to_f64 always succeeds since every
float can widen to f64. to_f32 fails with
Err(Precision) if the value is stored as f64.
A float internally stored as f16 can always be converted to either
an f32 or f64 for obvious reasons.
use cbor_core::Value;
let v = Value::from(2.5);
assert_eq!(v.to_f64().unwrap(), 2.5);
assert_eq!(v.to_f32().unwrap(), 2.5);§Byte strings
Byte strings are stored as Vec<u8>. Use as_bytes
for a borrowed slice, or into_bytes to take
ownership without copying.
| Method | Returns |
|---|---|
as_bytes | Result<&[u8]> |
as_bytes_mut | Result<&mut Vec<u8>> |
into_bytes | Result<Vec<u8>> |
use cbor_core::Value;
let mut v = Value::from(vec![1, 2, 3]);
v.as_bytes_mut().unwrap().push(4);
assert_eq!(v.as_bytes().unwrap(), &[1, 2, 3, 4]);§Text strings
Text strings are stored as String (guaranteed valid UTF-8 by the
decoder). Use as_str for a borrowed &str, or
into_string to take ownership.
| Method | Returns |
|---|---|
as_str | Result<&str> |
as_string_mut | Result<&mut String> |
into_string | Result<String> |
use cbor_core::Value;
let v = Value::from("hello");
assert_eq!(v.as_str().unwrap(), "hello");
// Modify in place
let mut v = Value::from("hello");
v.as_string_mut().unwrap().push_str(" world");
assert_eq!(v.as_str().unwrap(), "hello world");§Arrays
Arrays are stored as Vec<Value>. Use as_array
to borrow the elements as a slice, or as_array_mut
to modify them in place.
| Method | Returns |
|---|---|
as_array | Result<&[Value]> |
as_array_mut | Result<&mut Vec<Value>> |
into_array | Result<Vec<Value>> |
use cbor_core::{Value, array};
let v = array![10, 20, 30];
let items = v.as_array().unwrap();
assert_eq!(items[1].to_u32().unwrap(), 20);
// Modify in place
let mut v = array![1, 2];
v.as_array_mut().unwrap().push(3.into());
assert_eq!(v.as_array().unwrap().len(), 3);§Maps
Maps are stored as BTreeMap<Value, Value>, giving canonical key
order. Use standard BTreeMap methods on the result of
as_map to look up entries.
| Method | Returns |
|---|---|
as_map | Result<&BTreeMap<Value, Value>> |
as_map_mut | Result<&mut BTreeMap<Value, Value>> |
into_map | Result<BTreeMap<Value, Value>> |
use cbor_core::{Value, map};
let v = map! { "name" => "Alice", "age" => 30 };
assert_eq!(v["name"].as_str().unwrap(), "Alice");
// Modify in place
let mut v = map! { "count" => 1 };
v.as_map_mut().unwrap().insert("count".into(), 2.into());
assert_eq!(v["count"].to_u32().unwrap(), 2);§Indexing
Arrays and maps support Index and IndexMut with any type that
converts into Value. For arrays the index is converted to usize;
for maps it is used as a key lookup. Panics on type mismatch or
missing key, just like Vec and BTreeMap.
use cbor_core::{Value, array, map};
let a = array![10, 20, 30];
assert_eq!(a[1].to_u32().unwrap(), 20);
let m = map! { "x" => 10, "y" => 20 };
assert_eq!(m["x"].to_u32().unwrap(), 10);§Tags
A tag wraps another value with a numeric label (e.g. tag 1 for epoch timestamps, tag 32 for URIs). Tags can be nested.
| Method | Returns | Notes |
|---|---|---|
tag_number | Result<u64> | Tag number |
tag_content | Result<&Value> | Borrowed content |
tag_content_mut | Result<&mut Value> | Mutable content |
as_tag | Result<(u64, &Value)> | Both parts |
as_tag_mut | Result<(u64, &mut Value)> | Mutable content |
into_tag | Result<(u64, Value)> | Consuming |
Use untagged to look through tags without removing
them, remove_tag to strip the outermost tag, or
remove_all_tags to strip all layers at once.
use cbor_core::Value;
// Create a tagged value (tag 32 = URI)
let mut uri = Value::tag(32, "https://example.com");
// Inspect
let (tag_num, content) = uri.as_tag().unwrap();
assert_eq!(tag_num, 32);
assert_eq!(content.as_str().unwrap(), "https://example.com");
// Look through tags without removing them
assert_eq!(uri.untagged().as_str().unwrap(), "https://example.com");
// Strip the tag in place
let removed = uri.remove_tag();
assert_eq!(removed, Some(32));
assert_eq!(uri.as_str().unwrap(), "https://example.com");Accessor methods see through tags transparently: calling as_str()
on a tagged text string works without manually unwrapping the tag
first. This applies to all accessors (to_*, as_*, into_*).
use cbor_core::Value;
let uri = Value::tag(32, "https://example.com");
assert_eq!(uri.as_str().unwrap(), "https://example.com");
// Nested tags are also transparent
let nested = Value::tag(100, Value::tag(200, 42));
assert_eq!(nested.to_u32().unwrap(), 42);Big integers are internally represented as tagged byte strings
(tags 2 and 3). The integer accessors recognise these tags and
decode the bytes automatically, even when wrapped in additional
custom tags. Byte-level accessors like as_bytes() also see
through tags, so calling as_bytes() on a big integer returns
the raw payload bytes.
If a tag is removed via remove_tag, remove_all_tags, or by
consuming through into_tag, the value becomes a plain byte
string and can no longer be read as an integer.
§Type introspection
data_type returns a DataType enum for
lightweight type checks without matching on the full enum.
use cbor_core::Value;
let v = Value::from(3.14);
assert!(v.data_type().is_float());Variants§
SimpleValue(SimpleValue)
Simple value such as null, true, or false (major type 7).
In CBOR, booleans and null are simple values, not distinct types.
A Value::from(true) is stored as SimpleValue(21) and is
accessible through both to_bool and
to_simple_value.
Unsigned(u64)
Unsigned integer (major type 0). Stores values 0 through 2^64-1.
Negative(u64)
Negative integer (major type 1). The actual value is -1 - n, covering -1 through -2^64.
Float(Float)
IEEE 754 floating-point number (major type 7, additional info 25-27).
ByteString(Vec<u8>)
Byte string (major type 2).
TextString(String)
UTF-8 text string (major type 3).
Array(Vec<Value>)
Array of data items (major type 4).
Map(BTreeMap<Value, Value>)
Map of key-value pairs in canonical order (major type 5).
Tag(u64, Box<Value>)
Tagged data item (major type 6). The first field is the tag number, the second is the enclosed content.
Implementations§
Source§impl Value
impl Value
Sourcepub fn take(&mut self) -> Self
pub fn take(&mut self) -> Self
Take the value out, leaving null in its place.
use cbor_core::Value;
let mut v = Value::from(42);
let taken = v.take();
assert_eq!(taken.to_u32().unwrap(), 42);
assert!(v.data_type().is_null());Sourcepub fn replace(&mut self, value: Self) -> Self
pub fn replace(&mut self, value: Self) -> Self
Replace the value, returning the old one.
use cbor_core::Value;
let mut v = Value::from("hello");
let old = v.replace(Value::from("world"));
assert_eq!(old.as_str().unwrap(), "hello");
assert_eq!(v.as_str().unwrap(), "world");Sourcepub fn encode(&self) -> Vec<u8> ⓘ
pub fn encode(&self) -> Vec<u8> ⓘ
Encode this value to binary CBOR bytes.
This is a convenience wrapper around write_to.
use cbor_core::Value;
let bytes = Value::from(42).encode();
assert_eq!(bytes, [0x18, 42]);Sourcepub fn encode_hex(&self) -> String
pub fn encode_hex(&self) -> String
Encode this value to a hex-encoded CBOR string.
This is a convenience wrapper around write_hex_to.
use cbor_core::Value;
let hex = Value::from(42).encode_hex();
assert_eq!(hex, "182a");Sourcepub fn decode(bytes: impl AsRef<[u8]>) -> Result<Self>
pub fn decode(bytes: impl AsRef<[u8]>) -> Result<Self>
Decode a CBOR data item from binary bytes.
Accepts any byte source (&[u8], &str, String, Vec<u8>, etc.).
Returns Err if the encoding is not canonical.
This is a convenience wrapper around read_from.
use cbor_core::Value;
let v = Value::decode(&[0x18, 42]).unwrap();
assert_eq!(v.to_u32().unwrap(), 42);Sourcepub fn decode_hex(hex: impl AsRef<[u8]>) -> Result<Self>
pub fn decode_hex(hex: impl AsRef<[u8]>) -> Result<Self>
Decode a CBOR data item from hex-encoded bytes.
Accepts any byte source (&[u8], &str, String, Vec<u8>, etc.).
Both uppercase and lowercase hex digits are accepted.
Returns Err if the encoding is not canonical.
This is a convenience wrapper around read_hex_from.
use cbor_core::Value;
let v = Value::decode_hex("182a").unwrap();
assert_eq!(v.to_u32().unwrap(), 42);Sourcepub fn read_from(reader: &mut impl Read) -> Result<Self>
pub fn read_from(reader: &mut impl Read) -> Result<Self>
Read a single CBOR data item from a binary stream.
use cbor_core::Value;
let mut bytes: &[u8] = &[0x18, 42];
let v = Value::read_from(&mut bytes).unwrap();
assert_eq!(v.to_u32().unwrap(), 42);Sourcepub fn read_hex_from(reader: impl Read) -> Result<Self>
pub fn read_hex_from(reader: impl Read) -> Result<Self>
Read a single CBOR data item from a hex-encoded stream.
Each byte of CBOR is expected as two hex digits (uppercase or lowercase).
use cbor_core::Value;
let mut hex = "182a".as_bytes();
let v = Value::read_hex_from(&mut hex).unwrap();
assert_eq!(v.to_u32().unwrap(), 42);Sourcepub fn write_to(&self, writer: &mut impl Write) -> Result<()>
pub fn write_to(&self, writer: &mut impl Write) -> Result<()>
Write this value as binary CBOR to a stream.
use cbor_core::Value;
let mut buf = Vec::new();
Value::from(42).write_to(&mut buf).unwrap();
assert_eq!(buf, [0x18, 42]);Sourcepub fn write_hex_to(&self, writer: impl Write) -> Result<()>
pub fn write_hex_to(&self, writer: impl Write) -> Result<()>
Write this value as hex-encoded CBOR to a stream.
Each binary byte is written as two lowercase hex digits. The adapter encodes on the fly without buffering the full output.
use cbor_core::Value;
let mut buf = Vec::new();
Value::from(42).write_hex_to(&mut buf).unwrap();
assert_eq!(buf, b"182a");Sourcepub fn simple_value(value: impl TryInto<SimpleValue>) -> Self
pub fn simple_value(value: impl TryInto<SimpleValue>) -> Self
Create a CBOR simple value.
§Panics
Panics if the value is in the reserved range 24-31.
Use SimpleValue::from_u8 for a fallible alternative.
Sourcepub fn date_time(value: impl TryInto<DateTime>) -> Self
pub fn date_time(value: impl TryInto<DateTime>) -> Self
Create a CBOR date/time string value (tag 0).
Accepts &str, String, and SystemTime via the
DateTime helper. The date must be within
0001-01-01T00:00:00Z to 9999-12-31T23:59:59Z.
§Panics
Panics if the input is not a valid RFC 3339 (ISO 8601 profile) UTC timestamp or is out of range.
use cbor_core::{DataType, Value};
let v = Value::date_time("2000-01-01T00:00:00Z");
assert_eq!(v.data_type(), DataType::DateTime);
assert_eq!(v.as_str(), Ok("2000-01-01T00:00:00Z"));Sourcepub fn epoch_time(value: impl TryInto<EpochTime>) -> Self
pub fn epoch_time(value: impl TryInto<EpochTime>) -> Self
Create a CBOR epoch time value (tag 1).
Accepts integers, floats, and SystemTime via the
EpochTime helper. The value must be in the range 0 to
253402300799.
§Panics
Panics if the value is out of range or negative.
use std::time::{Duration, UNIX_EPOCH};
use cbor_core::Value;
let v = Value::epoch_time(1_000_000);
assert_eq!(v.to_system_time(), Ok(UNIX_EPOCH + Duration::from_secs(1_000_000)));Sourcepub fn float(value: impl Into<Float>) -> Self
pub fn float(value: impl Into<Float>) -> Self
Create a CBOR float.
Via the Float type floats can be created out of integers and booleans too.
use cbor_core::Value;
let f1 = Value::float(1.0);
assert!(f1.to_f64() == Ok(1.0));
let f2 = Value::float(2);
assert!(f2.to_f64() == Ok(2.0));
let f3 = Value::float(true);
assert!(f3.to_f64() == Ok(1.0));The value is stored in the shortest IEEE 754 form (f16, f32, or f64) that preserves it exactly.
Sourcepub fn array(array: impl Into<Array>) -> Self
pub fn array(array: impl Into<Array>) -> Self
Create a CBOR array from a Vec, slice, or fixed-size array.
Sourcepub fn tag(number: u64, content: impl Into<Value>) -> Self
pub fn tag(number: u64, content: impl Into<Value>) -> Self
Wrap a value with a CBOR tag.
use cbor_core::Value;
let uri = Value::tag(32, "https://example.com");
assert_eq!(uri.tag_number().unwrap(), 32);Sourcepub const fn data_type(&self) -> DataType
pub const fn data_type(&self) -> DataType
Return the DataType of this value for type-level dispatch.
Sourcepub const fn to_bool(&self) -> Result<bool>
pub const fn to_bool(&self) -> Result<bool>
Extract a boolean. Returns Err for non-boolean values.
Sourcepub const fn to_simple_value(&self) -> Result<u8>
pub const fn to_simple_value(&self) -> Result<u8>
Extract the raw simple value number (0-255, excluding 24-31).
Sourcepub fn to_u8(&self) -> Result<u8>
pub fn to_u8(&self) -> Result<u8>
Narrow to u8. Returns Err(Overflow) or Err(NegativeUnsigned) on mismatch.
Sourcepub fn to_u128(&self) -> Result<u128>
pub fn to_u128(&self) -> Result<u128>
Narrow to u128. Handles big integers (tag 2) transparently.
Sourcepub fn to_i128(&self) -> Result<i128>
pub fn to_i128(&self) -> Result<i128>
Narrow to i128. Handles big integers (tags 2 and 3) transparently.
Sourcepub fn to_f32(&self) -> Result<f32>
pub fn to_f32(&self) -> Result<f32>
Convert to f32. Returns Err(Precision) for f64-width values.
Sourcepub fn to_system_time(&self) -> Result<SystemTime>
pub fn to_system_time(&self) -> Result<SystemTime>
Convert a time value to SystemTime.
Accepts date/time strings (tag 0), epoch time values (tag 1), and untagged integers or floats. Numeric values must be non-negative and in the range 0 to 253402300799. Date/time strings may include a timezone offset, which is converted to UTC.
Returns Err(IncompatibleType) for values that are neither
numeric nor text, Err(Overflow) if a numeric value is out of
range, and Err(InvalidEncoding) if a text string is not a
valid RFC 3339 timestamp. Leap seconds (:60) are rejected
because SystemTime cannot represent them.
use std::time::{Duration, UNIX_EPOCH};
use cbor_core::Value;
let v = Value::tag(1, 1_000_000);
let t = v.to_system_time().unwrap();
assert_eq!(t, UNIX_EPOCH + Duration::from_secs(1_000_000));Sourcepub const fn as_bytes_mut(&mut self) -> Result<&mut Vec<u8>>
pub const fn as_bytes_mut(&mut self) -> Result<&mut Vec<u8>>
Borrow the byte string as a mutable Vec.
Sourcepub fn into_bytes(self) -> Result<Vec<u8>>
pub fn into_bytes(self) -> Result<Vec<u8>>
Take ownership of the byte string.
Sourcepub const fn as_string_mut(&mut self) -> Result<&mut String>
pub const fn as_string_mut(&mut self) -> Result<&mut String>
Borrow the text string as a mutable String.
Sourcepub fn into_string(self) -> Result<String>
pub fn into_string(self) -> Result<String>
Take ownership of the text string.
Sourcepub const fn as_array_mut(&mut self) -> Result<&mut Vec<Value>>
pub const fn as_array_mut(&mut self) -> Result<&mut Vec<Value>>
Borrow the array as a mutable Vec.
Sourcepub fn into_array(self) -> Result<Vec<Value>>
pub fn into_array(self) -> Result<Vec<Value>>
Take ownership of the array.
Sourcepub const fn as_map_mut(&mut self) -> Result<&mut BTreeMap<Value, Value>>
pub const fn as_map_mut(&mut self) -> Result<&mut BTreeMap<Value, Value>>
Borrow the map mutably.
Sourcepub fn get(&self, index: impl Into<Value>) -> Option<&Value>
pub fn get(&self, index: impl Into<Value>) -> Option<&Value>
Look up an element by index (arrays) or key (maps).
Returns None if the value is not an array or map, the index
is out of bounds, or the key is missing.
use cbor_core::{Value, array, map};
let a = array![10, 20, 30];
assert_eq!(a.get(1).unwrap().to_u32().unwrap(), 20);
assert!(a.get(5).is_none());
let m = map! { "x" => 10 };
assert_eq!(m.get("x").unwrap().to_u32().unwrap(), 10);
assert!(m.get("missing").is_none());Sourcepub fn get_mut(&mut self, index: impl Into<Value>) -> Option<&mut Value>
pub fn get_mut(&mut self, index: impl Into<Value>) -> Option<&mut Value>
Mutable version of get.
use cbor_core::{Value, array};
let mut a = array![10, 20, 30];
*a.get_mut(1).unwrap() = Value::from(99);
assert_eq!(a[1].to_u32().unwrap(), 99);Sourcepub const fn tag_number(&self) -> Result<u64>
pub const fn tag_number(&self) -> Result<u64>
Return the tag number.
Sourcepub const fn tag_content(&self) -> Result<&Self>
pub const fn tag_content(&self) -> Result<&Self>
Borrow the tag content.
Sourcepub const fn tag_content_mut(&mut self) -> Result<&mut Self>
pub const fn tag_content_mut(&mut self) -> Result<&mut Self>
Mutably borrow the tag content.
Sourcepub fn as_tag_mut(&mut self) -> Result<(u64, &mut Value)>
pub fn as_tag_mut(&mut self) -> Result<(u64, &mut Value)>
Borrow tag number and mutable content together.
Sourcepub fn remove_tag(&mut self) -> Option<u64>
pub fn remove_tag(&mut self) -> Option<u64>
Remove the outermost tag, returning its number. Returns None if
the value is not tagged.
Remove all nested tags, returning their numbers from outermost to innermost.
Sourcepub const fn untagged(&self) -> &Self
pub const fn untagged(&self) -> &Self
Borrow the innermost non-tag value, skipping all tag wrappers.
Sourcepub const fn untagged_mut(&mut self) -> &mut Self
pub const fn untagged_mut(&mut self) -> &mut Self
Mutable version of untagged.
Sourcepub fn into_untagged(self) -> Self
pub fn into_untagged(self) -> Self
Consuming version of untagged.