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_u32);
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_u32, 2, 3].as_slice());
// Map from a HashMap
let mut hm = HashMap::new();
hm.insert(1_u32, 2_u32);
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_i32);
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_u32);
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_i32);
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_f32);
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_u8, 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 };
let name = &v.as_map().unwrap()[&"name".into()];
assert_eq!(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.as_map().unwrap()[&"count".into()].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_u32].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_u32));
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_f64);
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_u32).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_u32).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_u32).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 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_u32);
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 const fn to_u8(&self) -> Result<u8>
pub const 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 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 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.