cbor_core/value.rs
1mod array;
2mod bytes;
3mod debug;
4mod eq_ord_hash;
5mod float;
6mod index;
7mod int;
8mod map;
9mod simple_value;
10mod string;
11
12use std::{
13 borrow::Cow,
14 collections::BTreeMap,
15 time::{Duration, SystemTime},
16};
17
18use crate::{
19 Array, ByteString, DataType, DateTime, EpochTime, Error, Float, IntegerBytes, Map, Result, SimpleValue, TextString,
20 codec::{Head, Major},
21 tag,
22 util::u128_from_slice,
23 view::{Payload, ValueView},
24};
25
26/// A single CBOR data item.
27///
28/// `Value` covers all CBOR major types: integers, floats, byte and text
29/// strings, arrays, maps, tagged values, and simple values (null, booleans).
30/// It encodes deterministically and decodes only canonical input.
31///
32/// # Creating values
33///
34/// Rust primitives convert via [`From`]:
35///
36/// ```
37/// use cbor_core::Value;
38///
39/// let n = Value::from(42);
40/// let s = Value::from("hello");
41/// let b = Value::from(true);
42/// ```
43///
44/// The [`array!`](crate::array) and [`map!`](crate::map) macros build arrays and maps from literals:
45///
46/// ```
47/// use cbor_core::{Value, array, map};
48///
49/// let a = array![1, 2, 3];
50/// let m = map! { "x" => 10, "y" => 20 };
51/// ```
52///
53/// Arrays and maps can also be built from standard Rust collections.
54/// Slices, `Vec`s, fixed-size arrays, `BTreeMap`s, `HashMap`s, and
55/// slices of key-value pairs all convert automatically:
56///
57/// ```
58/// use cbor_core::Value;
59/// use std::collections::HashMap;
60///
61/// // Array from a slice
62/// let a = Value::array([1, 2, 3].as_slice());
63///
64/// // Map from a HashMap
65/// let mut hm = HashMap::new();
66/// hm.insert(1, 2);
67/// let m = Value::map(&hm);
68///
69/// // Map from key-value pairs
70/// let m = Value::map([("x", 10), ("y", 20)]);
71/// ```
72///
73/// Use `()` to create empty arrays or maps without spelling out a type:
74///
75/// ```
76/// use cbor_core::Value;
77///
78/// let empty_array = Value::array(());
79/// let empty_map = Value::map(());
80///
81/// assert_eq!(empty_array.len(), Some(0));
82/// assert_eq!(empty_map.len(), Some(0));
83/// ```
84///
85/// Named constructors are available for cases where `From` is ambiguous
86/// or unavailable:
87///
88/// | Constructor | Builds |
89/// |---|---|
90/// | [`Value::new(v)`](Value::new) | Any variant via `TryFrom`, panicking on fallible failures |
91/// | [`Value::null()`] | Null simple value |
92/// | [`Value::simple_value(v)`](Value::simple_value) | Arbitrary simple value |
93/// | [`Value::float(v)`](Value::float) | Float in shortest CBOR form |
94/// | [`Value::byte_string(v)`](Value::byte_string) | Byte string from `impl Into<ByteString>` (borrows from `&[u8]`) |
95/// | [`Value::text_string(v)`](Value::text_string) | Text string from `impl Into<TextString>` (borrows from `&str`) |
96/// | [`Value::array(v)`](Value::array) | Array from slice, `Vec`, or fixed-size array |
97/// | [`Value::map(v)`](Value::map) | Map from `BTreeMap`, `HashMap`, slice of pairs, etc. |
98/// | [`Value::date_time(v)`](Value::date_time) | Date/time string (tag 0) |
99/// | [`Value::epoch_time(v)`](Value::epoch_time) | Epoch time (tag 1) |
100/// | [`Value::tag(n, v)`](Value::tag) | Tagged value |
101///
102/// # `const` constructors
103///
104/// Scalar variants can also be built in `const` context. These are the
105/// `const` counterparts of the `From<T>` implementations. Use them for
106/// `const` items; in non-`const` code the shorter `Value::from(v)` or
107/// [`Value::new(v)`](Value::new) spellings are preferred.
108///
109/// | Constructor | Builds |
110/// |---|---|
111/// | [`Value::null()`](Value::null) | Null simple value |
112/// | [`Value::simple_value(v)`](Value::simple_value) | Simple value from `u8` |
113/// | [`Value::from_bool(v)`](Value::from_bool) | Boolean |
114/// | [`Value::from_u64(v)`](Value::from_u64) | Unsigned integer |
115/// | [`Value::from_i64(v)`](Value::from_i64) | Signed integer |
116/// | [`Value::from_f32(v)`](Value::from_f32) | Float from `f32` |
117/// | [`Value::from_f64(v)`](Value::from_f64) | Float from `f64` |
118/// | [`Value::from_payload(v)`](Value::from_payload) | Non-finite float from payload |
119/// | [`Value::from_str_slice(s)`](Value::from_str_slice) | Borrowing text string from `&str` |
120/// | [`Value::from_byte_slice(b)`](Value::from_byte_slice) | Borrowing byte string from `&[u8]` |
121///
122/// Narrower integer widths (`u8`..`u32`, `i8`..`i32`) are not provided
123/// separately: `as u64` / `as i64` is lossless and yields the same
124/// `Value`. `u128` and `i128` have no `const` constructor because
125/// out-of-range values require the big-integer path, which allocates a
126/// tagged byte string. The text- and byte-string constructors are
127/// `const` only in their borrowing form (typically over `&'static`
128/// literals); owned `String` and `Vec<u8>` inputs need
129/// [`text_string`](Value::text_string) / [`byte_string`](Value::byte_string).
130/// Arrays, maps, and tags are heap-backed and cannot be built in
131/// `const` context at all.
132///
133/// # Encoding and decoding
134///
135/// ```
136/// use cbor_core::Value;
137///
138/// let original = Value::from(-1000);
139/// let bytes = original.encode();
140/// let decoded = Value::decode(&bytes).unwrap();
141/// assert_eq!(original, decoded);
142/// ```
143///
144/// CBOR can be produced and consumed as binary bytes, as a hex string,
145/// or as diagnostic notation text:
146///
147/// | Direction | Binary | Hex string | Diagnostic text |
148/// |---|---|---|---|
149/// | Produce (owned) | [`encode`](Value::encode) → `Vec<u8>` | [`encode_hex`](Value::encode_hex) → `String` | `format!("{v:?}")` (compact) or `format!("{v:#?}")` (pretty) via [`Debug`](std::fmt::Debug); `format!("{v}")` via [`Display`](std::fmt::Display) |
150/// | Produce (streaming) | [`write_to`](Value::write_to)(`impl Write`) | [`write_hex_to`](Value::write_hex_to)(`impl Write`) | — |
151/// | Consume (borrowed/owned) | [`decode`](Value::decode)(`&'a T) where T: AsRef<[u8]>`), [`decode_owned`](Value::decode_owned)(`impl AsRef<[u8]>`) | [`decode_hex`](Value::decode_hex)(`impl AsRef<[u8]>`) | [`str::parse`](str::parse) via [`FromStr`](std::str::FromStr) |
152/// | Consume (streaming) | [`read_from`](Value::read_from)(`impl Read`) | [`read_hex_from`](Value::read_hex_from)(`impl Read`) | — |
153///
154/// `Debug` output follows CBOR::Core diagnostic notation (Section 2.3.6);
155/// `Display` forwards to `Debug` so both produce the same text.
156/// `format!("{v:?}").parse::<Value>()` always round-trips.
157///
158/// The four decoding methods above forward to a default
159/// [`DecodeOptions`](crate::DecodeOptions). Use that type directly to
160/// switch between binary and hex at runtime, or to adjust the recursion
161/// limit, the declared-length cap, or the OOM-mitigation budget — for
162/// example, to tighten limits on input from an untrusted source:
163///
164/// ```
165/// use cbor_core::DecodeOptions;
166///
167/// let strict = DecodeOptions::new()
168/// .recursion_limit(16)
169/// .length_limit(4096)
170/// .oom_mitigation(64 * 1024);
171///
172/// let v = strict.decode(&[0x18, 42]).unwrap();
173/// assert_eq!(v.to_u32().unwrap(), 42);
174/// ```
175///
176/// To accept input from a producer that does not enforce
177/// CBOR::Core's deterministic encoding rules, pair `DecodeOptions`
178/// with [`Strictness`](crate::Strictness). Tolerated deviations are
179/// normalized while decoding, so the resulting `Value` is canonical
180/// and re-encoding it produces compliant bytes.
181///
182/// # Accessors
183///
184/// Accessor methods extract or borrow the inner data of each variant.
185/// All return [`Result<T>`](crate::Result), yielding [`Err(Error::IncompatibleType)`](Error::IncompatibleType)
186/// on a type mismatch. The naming follows Rust conventions:
187///
188/// | Prefix | Meaning | Returns |
189/// |---|---|---|
190/// | `as_*` | Borrow inner data | `&T` or `&mut T` (with `_mut`) |
191/// | `to_*` | Convert or narrow | Owned `Copy` type (`u8`, `f32`, ...) |
192/// | `into_*` | Consume self, extract | Owned `T` |
193/// | no prefix | Trivial property | `Copy` scalar |
194///
195/// ## Simple values
196///
197/// In CBOR, booleans and null are not distinct types but specific simple
198/// values: `false` is 20, `true` is 21, `null` is 22. This means a
199/// boolean value is always also a simple value. [`to_bool`](Self::to_bool)
200/// provides typed access to `true`/`false`, while
201/// [`to_simple_value`](Self::to_simple_value) works on any simple value
202/// including booleans and null.
203///
204/// | Method | Returns | Notes |
205/// |---|---|---|
206/// | [`to_simple_value`](Self::to_simple_value) | [`Result<u8>`](crate::Result) | Raw simple value number |
207/// | [`to_bool`](Self::to_bool) | [`Result<bool>`](crate::Result) | Only for `true`/`false` |
208///
209/// ```
210/// use cbor_core::Value;
211///
212/// let v = Value::from(true);
213/// assert_eq!(v.to_bool().unwrap(), true);
214/// assert_eq!(v.to_simple_value().unwrap(), 21); // CBOR true = simple(21)
215///
216/// // null is also a simple value
217/// let n = Value::null();
218/// assert!(n.to_bool().is_err()); // not a boolean
219/// assert_eq!(n.to_simple_value().unwrap(), 22); // but is simple(22)
220/// ```
221///
222/// ## Integers
223///
224/// CBOR has effectively four integer types (unsigned or negative, and
225/// normal or big integer) with different internal representations.
226/// This is handled transparently by the API.
227///
228/// The `to_*` accessors perform checked
229/// narrowing into any Rust integer type, returning [`Err(Overflow)`](Error::Overflow)
230/// if the value does not fit, or [`Err(NegativeUnsigned)`](Error::NegativeUnsigned)
231/// when extracting a negative value into an unsigned type.
232///
233/// | Method | Returns |
234/// |---|---|
235/// | [`to_u8`](Self::to_u8) .. [`to_u128`](Self::to_u128), [`to_usize`](Self::to_usize) | [`Result<uN>`](crate::Result) |
236/// | [`to_i8`](Self::to_i8) .. [`to_i128`](Self::to_i128), [`to_isize`](Self::to_isize) | [`Result<iN>`](crate::Result) |
237///
238/// ```
239/// use cbor_core::Value;
240///
241/// let v = Value::from(1000);
242/// assert_eq!(v.to_u32().unwrap(), 1000);
243/// assert_eq!(v.to_i64().unwrap(), 1000);
244/// assert!(v.to_u8().is_err()); // overflow
245///
246/// let neg = Value::from(-5);
247/// assert_eq!(neg.to_i8().unwrap(), -5);
248/// assert!(neg.to_u32().is_err()); // negative unsigned
249/// ```
250///
251/// ## Floats
252///
253/// Floats are stored internally in their shortest CBOR encoding (`f16`,
254/// `f32`, or `f64`). [`to_f64`](Self::to_f64) always succeeds since every
255/// float can widen to `f64`. [`to_f32`](Self::to_f32) fails with
256/// [`Err(Precision)`](Error::Precision) if the value is stored as `f64`.
257/// A float internally stored as `f16` can always be converted to either
258/// an `f32` or `f64` for obvious reasons.
259///
260/// | Method | Returns |
261/// |---|---|
262/// | [`to_f32`](Self::to_f32) | [`Result<f32>`](crate::Result) (fails for f64 values) |
263/// | [`to_f64`](Self::to_f64) | [`Result<f64>`](crate::Result) |
264///
265/// ```
266/// use cbor_core::Value;
267///
268/// let v = Value::from(2.5);
269/// assert_eq!(v.to_f64().unwrap(), 2.5);
270/// assert_eq!(v.to_f32().unwrap(), 2.5);
271/// ```
272///
273/// ## Byte strings
274///
275/// Byte strings are stored as `Vec<u8>`. Use [`as_bytes`](Self::as_bytes)
276/// for a borrowed slice, or [`into_bytes`](Self::into_bytes) to take
277/// ownership without copying.
278///
279/// | Method | Returns |
280/// |---|---|
281/// | [`as_bytes`](Self::as_bytes) | `Result<&[u8]>` |
282/// | [`as_bytes_mut`](Self::as_bytes_mut) | `Result<&mut Vec<u8>>` |
283/// | [`into_bytes`](Self::into_bytes) | `Result<Vec<u8>>` |
284///
285/// ```
286/// use cbor_core::Value;
287///
288/// let mut v = Value::from(vec![1, 2, 3]);
289/// v.as_bytes_mut().unwrap().push(4);
290/// assert_eq!(v.as_bytes().unwrap(), &[1, 2, 3, 4]);
291/// ```
292///
293/// ## Text strings
294///
295/// Text strings are stored as `String` (guaranteed valid UTF-8 by the
296/// decoder). Use [`as_str`](Self::as_str) for a borrowed `&str`, or
297/// [`into_string`](Self::into_string) to take ownership.
298///
299/// | Method | Returns |
300/// |---|---|
301/// | [`as_str`](Self::as_str) | `Result<&str>` |
302/// | [`as_string_mut`](Self::as_string_mut) | `Result<&mut String>` |
303/// | [`into_string`](Self::into_string) | `Result<String>` |
304///
305/// ```
306/// use cbor_core::Value;
307///
308/// let v = Value::from("hello");
309/// assert_eq!(v.as_str().unwrap(), "hello");
310///
311/// // Modify in place
312/// let mut v = Value::from("hello");
313/// v.as_string_mut().unwrap().push_str(" world");
314/// assert_eq!(v.as_str().unwrap(), "hello world");
315/// ```
316///
317/// ## Arrays
318///
319/// Arrays are stored as `Vec<Value>`. Use [`as_array`](Self::as_array)
320/// to borrow the elements as a slice, or [`as_array_mut`](Self::as_array_mut)
321/// to modify them in place. For element access by index, see
322/// [`get`](Self::get), [`get_mut`](Self::get_mut), [`remove`](Self::remove),
323/// and the [`Index`](std::ops::Index)/[`IndexMut`](std::ops::IndexMut)
324/// implementations — see the [Indexing](#indexing) section below.
325///
326/// | Method | Returns |
327/// |---|---|
328/// | [`as_array`](Self::as_array) | `Result<&[Value]>` |
329/// | [`as_array_mut`](Self::as_array_mut) | `Result<&mut Vec<Value>>` |
330/// | [`into_array`](Self::into_array) | `Result<Vec<Value>>` |
331///
332/// ```
333/// use cbor_core::{Value, array};
334///
335/// let v = array![10, 20, 30];
336/// let items = v.as_array().unwrap();
337/// assert_eq!(items[1].to_u32().unwrap(), 20);
338///
339/// // Modify in place
340/// let mut v = array![1, 2];
341/// v.append(3);
342/// assert_eq!(v.len(), Some(3));
343/// ```
344///
345/// ## Maps
346///
347/// Maps are stored as `BTreeMap<Value, Value>`, giving canonical key
348/// order. Use [`as_map`](Self::as_map) for direct access to the
349/// underlying `BTreeMap`, or [`get`](Self::get), [`get_mut`](Self::get_mut),
350/// [`remove`](Self::remove), and the [`Index`](std::ops::Index)/
351/// [`IndexMut`](std::ops::IndexMut) implementations for key lookups — see the
352/// [Indexing](#indexing) section below.
353///
354/// | Method | Returns |
355/// |---|---|
356/// | [`as_map`](Self::as_map) | `Result<&BTreeMap<Value, Value>>` |
357/// | [`as_map_mut`](Self::as_map_mut) | `Result<&mut BTreeMap<Value, Value>>` |
358/// | [`into_map`](Self::into_map) | `Result<BTreeMap<Value, Value>>` |
359///
360/// ```
361/// use cbor_core::{Value, map};
362///
363/// let v = map! { "name" => "Alice", "age" => 30 };
364/// assert_eq!(v["name"].as_str().unwrap(), "Alice");
365///
366/// // Modify in place
367/// let mut v = map! { "count" => 1 };
368/// v.insert("count", 2);
369/// assert_eq!(v["count"].to_u32().unwrap(), 2);
370/// ```
371///
372/// ## Indexing
373///
374/// Arrays and maps share a uniform interface for element access,
375/// summarized below. Entries with a shaded "Panics" cell never panic
376/// under any inputs.
377///
378/// | Method | Returns | Non-collection receiver | Invalid / missing key |
379/// |---|---|---|---|
380/// | [`len`](Self::len) | `Option<usize>` | `None` | — |
381/// | [`contains`](Self::contains) | `bool` | `false` | `false` |
382/// | [`get`](Self::get) | `Option<&Value>` | `None` | `None` |
383/// | [`get_mut`](Self::get_mut) | `Option<&mut Value>` | `None` | `None` |
384/// | [`insert`](Self::insert) | `Option<Value>` (arrays: always `None`) | **panics** | array: **panics**; map: inserts |
385/// | [`remove`](Self::remove) | `Option<Value>` | **panics** | array: **panics**; map: `None` |
386/// | [`append`](Self::append) | `()` | **panics** (maps included) | — |
387/// | `v[key]`, `v[key] = …` | `&Value`, `&mut Value` | **panics** | **panics** |
388///
389/// The methods split into two flavors:
390///
391/// - **Soft** — [`len`](Self::len), [`contains`](Self::contains),
392/// [`get`](Self::get), and [`get_mut`](Self::get_mut): never panic.
393/// They return `Option`/`bool` and treat a wrong-type receiver the
394/// same as a missing key.
395/// - **Hard** — [`insert`](Self::insert), [`remove`](Self::remove),
396/// [`append`](Self::append), and the `[]` operators: panic when the
397/// receiver is not an array or map, when an array index is not a
398/// valid `usize` (negative, non-integer key), or when the index is
399/// out of range. This mirrors [`Vec`] and
400/// [`BTreeMap`](std::collections::BTreeMap).
401///
402/// All keyed methods accept any type implementing
403/// `Into<`[`ValueKey`](crate::ValueKey)`>`: integers (for array indices
404/// and integer map keys), `&str`, `&[u8]`, `&Value`, and the primitive
405/// CBOR types.
406/// [`insert`](Self::insert) takes `Into<Value>` for the key, since a
407/// map insert has to own the key anyway.
408///
409/// All methods see through tags transparently — operating on a
410/// [`Tag`](Self::Tag) dispatches to the innermost tagged content.
411///
412/// ### Arrays
413///
414/// The key is always a `usize` index. Valid ranges differ by method:
415///
416/// - [`get`](Self::get), [`get_mut`](Self::get_mut),
417/// [`contains`](Self::contains), [`remove`](Self::remove), and `v[i]`
418/// require `i` to be in `0..len`.
419/// [`get`](Self::get)/[`get_mut`](Self::get_mut)/[`contains`](Self::contains)
420/// return `None`/`false` for invalid or out-of-range indices;
421/// [`remove`](Self::remove) and `v[i]` panic.
422/// - [`insert`](Self::insert) accepts `0..=len` (appending at `len`
423/// is allowed) and shifts subsequent elements right. It always
424/// returns `None`, and panics if the index is invalid or out of
425/// range.
426/// - [`append`](Self::append) pushes to the end in O(1) and never
427/// cares about an index.
428/// - [`insert`](Self::insert) and [`remove`](Self::remove) shift
429/// elements, which is O(n) and can be slow for large arrays. Prefer
430/// [`append`](Self::append) when order at the end is all you need.
431/// - To replace an element in place (O(1), no shift), assign through
432/// [`get_mut`](Self::get_mut) or `v[i] = …`.
433///
434/// ### Maps
435///
436/// The key is any CBOR-convertible value:
437///
438/// - [`insert`](Self::insert) returns the previous value if the key
439/// was already present, otherwise `None` — matching
440/// [`BTreeMap::insert`](std::collections::BTreeMap::insert).
441/// - [`remove`](Self::remove) returns the removed value, or `None` if
442/// the key was absent. It never panics on a missing key (maps have
443/// no notion of an out-of-range key).
444/// - [`get`](Self::get), [`get_mut`](Self::get_mut), and
445/// [`contains`](Self::contains) return `None`/`false` for missing
446/// keys; `v[key]` panics.
447/// - [`append`](Self::append) is an array-only operation and panics
448/// when called on a map.
449///
450/// ### Example
451///
452/// ```
453/// use cbor_core::{Value, array, map};
454///
455/// // --- arrays ---
456/// let mut a = array![10, 30];
457/// a.insert(1, 20); // shift-insert at index 1
458/// a.append(40); // push to end
459/// assert_eq!(a.len(), Some(4));
460/// a[0] = Value::from(99); // O(1) in-place replace
461/// assert_eq!(a.remove(0).unwrap().to_u32().unwrap(), 99);
462/// assert!(a.contains(0));
463/// assert_eq!(a.get(5), None); // out of range: soft miss
464///
465/// // --- maps ---
466/// let mut m = map! { "x" => 10 };
467/// assert_eq!(m.insert("y", 20), None); // new key
468/// assert_eq!(m.insert("x", 99).unwrap().to_u32().unwrap(), 10);
469/// assert_eq!(m["x"].to_u32().unwrap(), 99);
470/// assert_eq!(m.remove("missing"), None); // missing key: no panic
471/// assert!(!m.contains("missing"));
472/// ```
473///
474/// ## Tags
475///
476/// A tag wraps another value with a numeric label (e.g. tag 1 for epoch
477/// timestamps, tag 32 for URIs). Tags can be nested.
478///
479/// | Method | Returns | Notes |
480/// |---|---|---|
481/// | [`tag_number`](Self::tag_number) | `Result<u64>` | Tag number |
482/// | [`tag_content`](Self::tag_content) | `Result<&Value>` | Borrowed content |
483/// | [`tag_content_mut`](Self::tag_content_mut) | `Result<&mut Value>` | Mutable content |
484/// | [`as_tag`](Self::as_tag) | `Result<(u64, &Value)>` | Both parts |
485/// | [`as_tag_mut`](Self::as_tag_mut) | `Result<(u64, &mut Value)>` | Mutable content |
486/// | [`into_tag`](Self::into_tag) | `Result<(u64, Value)>` | Consuming |
487///
488/// Use [`untagged`](Self::untagged) to look through tags without removing
489/// them, [`remove_tag`](Self::remove_tag) to strip the outermost tag, or
490/// [`remove_all_tags`](Self::remove_all_tags) to strip all layers at once.
491///
492/// ```
493/// use cbor_core::Value;
494///
495/// // Create a tagged value (tag 32 = URI)
496/// let mut uri = Value::tag(32, "https://example.com");
497///
498/// // Inspect
499/// let (tag_num, content) = uri.as_tag().unwrap();
500/// assert_eq!(tag_num, 32);
501/// assert_eq!(content.as_str().unwrap(), "https://example.com");
502///
503/// // Look through tags without removing them
504/// assert_eq!(uri.untagged().as_str().unwrap(), "https://example.com");
505///
506/// // Strip the tag in place
507/// let removed = uri.remove_tag();
508/// assert_eq!(removed, Some(32));
509/// assert_eq!(uri.as_str().unwrap(), "https://example.com");
510/// ```
511///
512/// Accessor methods see through tags transparently: calling `as_str()`
513/// on a tagged text string works without manually unwrapping the tag
514/// first. This applies to all accessors (`to_*`, `as_*`, `into_*`).
515///
516/// ```
517/// use cbor_core::Value;
518///
519/// let uri = Value::tag(32, "https://example.com");
520/// assert_eq!(uri.as_str().unwrap(), "https://example.com");
521///
522/// // Nested tags are also transparent
523/// let nested = Value::tag(100, Value::tag(200, 42));
524/// assert_eq!(nested.to_u32().unwrap(), 42);
525/// ```
526///
527/// Big integers are internally represented as tagged byte strings
528/// (tags 2 and 3). The integer accessors recognise these tags and
529/// decode the bytes automatically, even when wrapped in additional
530/// custom tags. Byte-level accessors like [`as_bytes()`](Self::as_bytes)
531/// also see through tags, so calling [`as_bytes()`](Self::as_bytes)
532/// on a big integer returns the raw payload bytes.
533///
534/// If a tag is removed via [`remove_tag`](Self::remove_tag),
535/// [`remove_all_tags`](Self::remove_all_tags), or by consuming through
536/// [`into_tag`](Self::into_tag), the value becomes a plain byte
537/// string and can no longer be read as an integer.
538///
539/// # Type introspection
540///
541/// [`data_type`](Self::data_type) returns a [`DataType`] enum that
542/// classifies the value by major type, plus a few promoted variants
543/// for well-known tag/content combinations
544/// ([`DateTime`](DataType::DateTime), [`EpochTime`](DataType::EpochTime),
545/// [`BigInt`](DataType::BigInt)). Use it for cheap type checks and
546/// dispatch without matching on the full [`Value`] enum.
547///
548/// `DataType` carries a family of `is_*` predicates that group related
549/// variants by semantic role: [`is_integer`](DataType::is_integer)
550/// covers both [`Int`](DataType::Int) and [`BigInt`](DataType::BigInt),
551/// [`is_float`](DataType::is_float) covers all three precisions, and
552/// so on.
553///
554/// ```
555/// use cbor_core::Value;
556///
557/// let v = Value::from(3.14);
558/// assert!(v.data_type().is_float());
559///
560/// // BigInt counts as an integer even though it's a tagged byte string.
561/// let big = Value::from(u128::MAX);
562/// assert!(big.data_type().is_integer());
563/// ```
564#[derive(Clone)]
565pub enum Value<'a> {
566 /// Simple value such as `null`, `true`, or `false` (major type 7).
567 ///
568 /// In CBOR, booleans and null are simple values, not distinct types.
569 /// A `Value::from(true)` is stored as `SimpleValue(21)` and is
570 /// accessible through both [`to_bool`](Self::to_bool) and
571 /// [`to_simple_value`](Self::to_simple_value).
572 ///
573 /// ```
574 /// # use cbor_core::Value;
575 /// let sv = Value::null();
576 /// assert!(sv.data_type().is_simple_value() && sv.data_type().is_null());
577 ///
578 /// let sv = Value::new(false);
579 /// assert!(sv.data_type().is_simple_value() && sv.data_type().is_bool());
580 /// ```
581 SimpleValue(SimpleValue),
582
583 /// Unsigned integer (major type 0). Stores values 0 through 2^64-1.
584 ///
585 /// ```
586 /// # use cbor_core::Value;
587 /// let v = Value::new(42);
588 /// # assert!(v.data_type().is_integer());
589 /// ```
590 Unsigned(u64),
591
592 /// Negative integer (major type 1). The actual value is -1 - n,
593 /// covering -1 through -2^64.
594 ///
595 /// ```
596 /// # use cbor_core::Value;
597 /// let v = Value::new(-42);
598 /// # assert!(v.data_type().is_integer());
599 /// ```
600 Negative(u64),
601
602 /// IEEE 754 floating-point number (major type 7, additional info 25-27).
603 ///
604 /// ```
605 /// # use cbor_core::Value;
606 /// let v = Value::new(1.234);
607 /// # assert!(v.data_type().is_float());
608 /// ```
609 Float(Float),
610
611 /// Byte string (major type 2).
612 ///
613 /// ```
614 /// # use cbor_core::Value;
615 /// let v = Value::new(b"this is a byte string");
616 /// # assert!(v.data_type().is_bytes());
617 /// ```
618 ByteString(Cow<'a, [u8]>),
619
620 /// UTF-8 text string (major type 3).
621 ///
622 /// ```
623 /// # use cbor_core::Value;
624 /// let v = Value::new("Rust + CBOR::Core");
625 /// # assert!(v.data_type().is_text());
626 /// ```
627 TextString(Cow<'a, str>),
628
629 /// Array of data items (major type 4).
630 ///
631 /// ```
632 /// use cbor_core::array;
633 /// let v = array![1, 2, 3, "text", b"bytes", true, 1.234, array![4,5,6]];
634 /// # assert!(v.data_type().is_array());
635 /// ```
636 Array(Vec<Value<'a>>),
637
638 /// Map of key-value pairs in canonical order (major type 5).
639 ///
640 /// ```
641 /// use cbor_core::{map, array};
642 /// let v = map!{"answer" => 42, array![1,2,3] => "arrays as keys" };
643 /// # assert!(v.data_type().is_map());
644 /// ```
645 Map(BTreeMap<Value<'a>, Value<'a>>),
646
647 /// Tagged data item (major type 6). The first field is the tag number,
648 /// the second is the enclosed content.
649 ///
650 /// ```
651 /// # use cbor_core::Value;
652 /// let v = Value::tag(0, "1955-11-12T22:04:00-08:00");
653 /// # assert!(v.data_type().is_tag());
654 /// ```
655 Tag(u64, Box<Value<'a>>),
656}
657
658impl Default for Value<'_> {
659 fn default() -> Self {
660 Self::null()
661 }
662}
663
664impl From<()> for Value<'_> {
665 fn from((): ()) -> Self {
666 Value::null()
667 }
668}
669
670/// Constructors
671impl<'a> Value<'a> {
672 /// Create a CBOR null value.
673 ///
674 /// In CBOR, null is the simple value 22.
675 ///
676 /// ```
677 /// use cbor_core::Value;
678 ///
679 /// let v = Value::null();
680 /// assert!(v.data_type().is_null());
681 /// assert!(v.data_type().is_simple_value());
682 /// assert_eq!(v.to_simple_value(), Ok(22));
683 /// ```
684 #[must_use]
685 pub const fn null() -> Self {
686 Self::SimpleValue(SimpleValue::NULL)
687 }
688
689 /// Create a CBOR simple value. Usable in `const` context.
690 ///
691 /// # Panics
692 ///
693 /// Panics if the value is in the reserved range 24-31.
694 /// Use [`SimpleValue::from_u8`] for a fallible alternative.
695 ///
696 /// ```
697 /// use cbor_core::Value;
698 ///
699 /// const V: Value = Value::simple_value(42);
700 /// assert_eq!(V.to_simple_value(), Ok(42));
701 /// ```
702 #[must_use]
703 pub const fn simple_value(value: u8) -> Self {
704 match SimpleValue::from_u8(value) {
705 Ok(sv) => Self::SimpleValue(sv),
706 Err(_) => panic!("Invalid simple value"),
707 }
708 }
709
710 /// Create a boolean `Value`, usable in `const` context.
711 ///
712 /// `const` counterpart of `Value::from(value)` for booleans. In CBOR,
713 /// `false` is simple value 20 and `true` is simple value 21.
714 ///
715 /// ```
716 /// use cbor_core::Value;
717 ///
718 /// const T: Value = Value::from_bool(true);
719 /// assert_eq!(T.to_bool(), Ok(true));
720 /// ```
721 #[must_use]
722 pub const fn from_bool(value: bool) -> Self {
723 Self::SimpleValue(SimpleValue::from_bool(value))
724 }
725
726 /// Create an unsigned integer `Value`, usable in `const` context.
727 ///
728 /// `const` counterpart of `Value::from(value)` for unsigned integers.
729 /// Smaller widths (`u8`, `u16`, `u32`) are intentionally not provided
730 /// as separate constructors: the `as u64` widening is lossless and
731 /// the resulting `Value` is identical regardless of the source width.
732 ///
733 /// `u128` has no `const` constructor because values above `u64::MAX`
734 /// require the big-integer path, which allocates a tagged byte string.
735 ///
736 /// ```
737 /// use cbor_core::Value;
738 ///
739 /// const V: Value = Value::from_u64(42);
740 /// assert_eq!(V.to_u64(), Ok(42));
741 /// ```
742 #[must_use]
743 pub const fn from_u64(value: u64) -> Self {
744 Self::Unsigned(value)
745 }
746
747 /// Create a signed integer `Value`, usable in `const` context.
748 ///
749 /// `const` counterpart of `Value::from(value)` for signed integers.
750 /// Smaller widths (`i8`, `i16`, `i32`) are intentionally not provided
751 /// as separate constructors: the `as i64` widening is lossless and
752 /// the resulting `Value` is identical regardless of the source width.
753 ///
754 /// `i128` has no `const` constructor for the same reason as
755 /// [`from_u64`](Self::from_u64): out-of-`i64`-range values need the
756 /// big-integer path, which allocates.
757 ///
758 /// ```
759 /// use cbor_core::Value;
760 ///
761 /// const V: Value = Value::from_i64(-42);
762 /// assert_eq!(V.to_i64(), Ok(-42));
763 /// ```
764 #[must_use]
765 pub const fn from_i64(value: i64) -> Self {
766 if value >= 0 {
767 Self::Unsigned(value as u64)
768 } else {
769 Self::Negative((!value) as u64)
770 }
771 }
772
773 /// Create a float `Value` from `f32`, usable in `const` context.
774 ///
775 /// `const` counterpart of `Value::from(value)` for `f32`. NaN
776 /// payloads are preserved. The result is stored in the shortest
777 /// CBOR form (f16, f32, or f64) that represents the value exactly.
778 ///
779 /// Prefer this over `Value::from_f64(x as f64)` when `x` is already
780 /// an `f32`: the `as f64` cast is lossless, but routing through
781 /// `from_f32` is clearer about intent and preserves NaN payloads
782 /// without relying on hardware canonicalization.
783 ///
784 /// ```
785 /// use cbor_core::Value;
786 ///
787 /// const V: Value = Value::from_f32(1.0);
788 /// assert_eq!(V.to_f32(), Ok(1.0));
789 /// ```
790 #[must_use]
791 pub const fn from_f32(value: f32) -> Self {
792 Self::Float(Float::from_f32(value))
793 }
794
795 /// Create a float `Value` from `f64`, usable in `const` context.
796 ///
797 /// `const` counterpart of `Value::from(value)` for `f64`. The result
798 /// is stored in the shortest CBOR form (f16, f32, or f64) that
799 /// represents the value exactly, NaN payloads included.
800 ///
801 /// ```
802 /// use cbor_core::Value;
803 ///
804 /// const V: Value = Value::from_f64(1.5);
805 /// assert_eq!(V.to_f64(), Ok(1.5));
806 /// ```
807 #[must_use]
808 pub const fn from_f64(value: f64) -> Self {
809 Self::Float(Float::from_f64(value))
810 }
811
812 /// Create a non-finite float `Value` from a 53-bit payload, usable
813 /// in `const` context.
814 ///
815 /// Payloads encode the kind of non-finite float (Infinity, NaN) and
816 /// its signalling bits in a width-invariant layout. The typical use
817 /// is defining `const` sentinel values that signal application-level
818 /// conditions through NaN payloads. See [`Float::with_payload`] for
819 /// the payload layout.
820 ///
821 /// # Panics
822 ///
823 /// Panics if `payload` exceeds the 53-bit maximum
824 /// (`0x1f_ffff_ffff_ffff`). Inputs within the 53-bit range never
825 /// panic.
826 ///
827 /// ```
828 /// use cbor_core::Value;
829 ///
830 /// const INF: Value = Value::from_payload(0);
831 /// assert!(INF.to_f64().unwrap().is_infinite());
832 /// ```
833 #[must_use]
834 pub const fn from_payload(payload: u64) -> Self {
835 Self::Float(Float::with_payload(payload))
836 }
837
838 /// Create a borrowing [`Value::TextString`] from a string slice,
839 /// usable in `const` context.
840 ///
841 /// `const` counterpart of `Value::from(s)` and
842 /// [`Value::text_string(s)`](Self::text_string) for `&str` input.
843 /// The resulting value borrows from `s`; its lifetime is tied to
844 /// the input slice, which makes the constructor especially
845 /// suitable for `const` items pointing at string literals
846 /// (`&'static str`).
847 ///
848 /// Named `from_str_slice` rather than `from_str` to avoid shadowing
849 /// the [`FromStr`](std::str::FromStr) implementation, which parses
850 /// diagnostic notation and is semantically very different.
851 ///
852 /// ```
853 /// use cbor_core::Value;
854 ///
855 /// const HELLO: Value = Value::from_str_slice("hello");
856 /// assert_eq!(HELLO.as_str(), Ok("hello"));
857 /// ```
858 #[must_use]
859 pub const fn from_str_slice(s: &'a str) -> Self {
860 Self::TextString(Cow::Borrowed(s))
861 }
862
863 /// Create a borrowing [`Value::ByteString`] from a byte slice,
864 /// usable in `const` context.
865 ///
866 /// `const` counterpart of `Value::from(b)` and
867 /// [`Value::byte_string(b)`](Self::byte_string) for `&[u8]` input.
868 /// The resulting value borrows from `b`; its lifetime is tied to
869 /// the input slice, which makes the constructor especially
870 /// suitable for `const` items pointing at byte-array literals
871 /// (`&'static [u8]`).
872 ///
873 /// ```
874 /// use cbor_core::Value;
875 ///
876 /// const BYTES: Value = Value::from_byte_slice(&[1, 2, 3]);
877 /// assert_eq!(BYTES.as_bytes(), Ok([1, 2, 3].as_slice()));
878 /// ```
879 #[must_use]
880 pub const fn from_byte_slice(b: &'a [u8]) -> Self {
881 Self::ByteString(Cow::Borrowed(b))
882 }
883
884 /// Create a CBOR value, inferring the variant from the input type.
885 ///
886 /// Equivalent to `Value::try_from(value).unwrap()`.
887 ///
888 /// Not every CBOR variant is reachable this way. Use the dedicated
889 /// constructors for the remaining cases.
890 ///
891 /// Whether this can panic depends on which conversion the input
892 /// type provides:
893 ///
894 /// - Types with `impl From<T> for Value` never panic here. `From`
895 /// is infallible by contract, and the standard blanket
896 /// `impl<T, U: Into<T>> TryFrom<U> for T` routes through it
897 /// without introducing a failure case. For these types,
898 /// [`Value::from`] is the more direct spelling.
899 /// - Types with an explicit `impl TryFrom<T> for Value` (mainly
900 /// the date- and time-related ones) can fail. `Value::new`
901 /// unwraps the error and panics. Call `Value::try_from` instead
902 /// to handle it.
903 ///
904 /// # Panics
905 ///
906 /// Panics if the input cannot be converted into a CBOR value.
907 #[must_use]
908 pub fn new(value: impl TryInto<Value<'a>>) -> Self {
909 match value.try_into() {
910 Ok(value) => value,
911 Err(_) => panic!("Invalid CBOR value"),
912 }
913 }
914
915 /// Create a CBOR byte string (major type 2).
916 ///
917 /// Accepts anything that converts into [`ByteString<'a>`]:
918 ///
919 /// - `&'a [u8]` and `&'a [u8; N]` borrow zero-copy from the input.
920 /// - Owned `Vec<u8>` is moved without copying.
921 /// - Fixed-size `[u8; N]` and `Cow<'a, [u8]>` are accepted as well.
922 ///
923 /// ```
924 /// use cbor_core::Value;
925 ///
926 /// // Borrowed: tied to the slice's lifetime.
927 /// let v = Value::byte_string(b"ABC");
928 /// assert_eq!(v.as_bytes(), Ok([65, 66, 67].as_slice()));
929 ///
930 /// // Owned: holds the Vec without reallocating.
931 /// let v = Value::byte_string(vec![1, 2, 3]);
932 /// assert_eq!(v.as_bytes(), Ok([1, 2, 3].as_slice()));
933 /// ```
934 #[must_use]
935 pub fn byte_string(value: impl Into<ByteString<'a>>) -> Self {
936 Value::from(value.into())
937 }
938
939 /// Create a CBOR text string (major type 3).
940 ///
941 /// Accepts anything that converts into [`TextString<'a>`]:
942 ///
943 /// - `&'a str` (and any `&'a T` with `T: AsRef<str>`) borrows
944 /// zero-copy from the input.
945 /// - Owned `String` is moved without copying.
946 /// - `char` and `Cow<'a, str>` are accepted as well; `char`
947 /// allocates a one-character `String`.
948 ///
949 /// ```
950 /// use cbor_core::Value;
951 ///
952 /// // Borrowed: tied to the string slice's lifetime.
953 /// let v = Value::text_string("hello");
954 /// assert_eq!(v.as_str(), Ok("hello"));
955 ///
956 /// // Owned char input.
957 /// let v = Value::text_string('A');
958 /// assert_eq!(v.as_str(), Ok("A"));
959 /// ```
960 #[must_use]
961 pub fn text_string(value: impl Into<TextString<'a>>) -> Self {
962 Self::from(value.into())
963 }
964
965 /// Create a CBOR date/time string value (tag 0).
966 ///
967 /// Accepts `&str`, `String`, and [`SystemTime`] via the
968 /// [`DateTime`] helper.
969 ///
970 /// The date must be within
971 /// `0000-01-01T00:00:00Z` to `9999-12-31T23:59:59Z`.
972 ///
973 /// # Panics
974 ///
975 /// Panics if the input is not a valid RFC 3339 (ISO 8601 profile)
976 /// UTC timestamp or is out of range.
977 ///
978 /// ```
979 /// use cbor_core::{DataType, Value};
980 ///
981 /// let v = Value::date_time("2000-01-01T00:00:00.000+01:00");
982 /// assert!(v.data_type().is_date_time());
983 /// assert_eq!(v.as_str(), Ok("2000-01-01T00:00:00.000+01:00"));
984 ///
985 /// use std::time::SystemTime;
986 /// let v = Value::date_time(SystemTime::UNIX_EPOCH);
987 /// assert!(v.data_type().is_date_time());
988 /// assert_eq!(v.as_str(), Ok("1970-01-01T00:00:00Z"));
989 /// ```
990 #[must_use]
991 pub fn date_time(value: impl TryInto<DateTime>) -> Self {
992 match value.try_into() {
993 Ok(dt) => dt.into(),
994 Err(_) => panic!("Invalid date/time"),
995 }
996 }
997
998 /// Create a CBOR epoch time value (tag 1).
999 ///
1000 /// Accepts integers, floats, and [`SystemTime`] via the
1001 /// [`EpochTime`] helper. The value must be in the range 0 to
1002 /// 253402300799.
1003 ///
1004 /// # Panics
1005 ///
1006 /// Panics if the value is out of range or negative.
1007 ///
1008 /// ```
1009 /// use std::time::{Duration, UNIX_EPOCH};
1010 /// use cbor_core::Value;
1011 ///
1012 /// let v = Value::epoch_time(1_000_000);
1013 /// assert_eq!(v.to_system_time(), Ok(UNIX_EPOCH + Duration::from_secs(1_000_000)));
1014 /// ```
1015 #[must_use]
1016 pub fn epoch_time(value: impl TryInto<EpochTime>) -> Self {
1017 match value.try_into() {
1018 Ok(et) => et.into(),
1019 Err(_) => panic!("Invalid epoch time"),
1020 }
1021 }
1022
1023 /// Create a CBOR float.
1024 ///
1025 /// Via the [`Float`] type floats can be created out of integers and booleans too.
1026 ///
1027 /// ```
1028 /// use cbor_core::Value;
1029 ///
1030 /// let f1 = Value::float(1.0);
1031 /// assert!(f1.to_f64() == Ok(1.0));
1032 ///
1033 /// let f2 = Value::float(2);
1034 /// assert!(f2.to_f64() == Ok(2.0));
1035 ///
1036 /// let f3 = Value::float(true);
1037 /// assert!(f3.to_f64() == Ok(1.0));
1038 /// ```
1039 ///
1040 /// The value is stored in the shortest IEEE 754 form (f16, f32,
1041 /// or f64) that preserves it exactly.
1042 #[must_use]
1043 pub fn float(value: impl Into<Float>) -> Self {
1044 Self::Float(value.into())
1045 }
1046
1047 /// Create a CBOR array.
1048 ///
1049 /// Accepts any type that converts into [`Array`], including
1050 /// `Vec<T>`, `[T; N]`, `&[T]`, and `Box<[T]>` where `T: Into<Value>`.
1051 ///
1052 /// See [`Array`] for the full list of accepted types.
1053 ///
1054 /// ```
1055 /// # use cbor_core::Value;
1056 /// let a = Value::array([1, 2, 3]);
1057 /// assert_eq!(a.len(), Some(3));
1058 /// ```
1059 #[must_use]
1060 pub fn array(array: impl Into<Array<'a>>) -> Self {
1061 Self::Array(array.into().0)
1062 }
1063
1064 /// Create a CBOR map. Keys are stored in canonical order.
1065 ///
1066 /// Accepts any type that converts into [`Map`], including
1067 /// `BTreeMap`, `&HashMap`, `Vec<(K, V)>`, `[(K, V); N]`, and
1068 /// `&[(K, V)]`.
1069 ///
1070 /// See [`Map`] for the full list of accepted types.
1071 ///
1072 /// ```
1073 /// # use cbor_core::Value;
1074 /// let m = Value::map([("x", 1), ("y", 2)]);
1075 /// assert_eq!(m.len(), Some(2));
1076 /// ```
1077 #[must_use]
1078 pub fn map(map: impl Into<Map<'a>>) -> Self {
1079 Self::Map(map.into().0)
1080 }
1081
1082 /// Wrap a value with a CBOR tag.
1083 ///
1084 /// ```
1085 /// use cbor_core::Value;
1086 /// let uri = Value::tag(32, "https://example.com");
1087 /// assert_eq!(uri.tag_number().unwrap(), 32);
1088 /// ```
1089 #[must_use]
1090 pub fn tag(number: u64, content: impl Into<Value<'a>>) -> Self {
1091 Self::Tag(number, Box::new(content.into()))
1092 }
1093
1094 /// Clone a `Value<'a>` into an independently owned `Value<'b>`.
1095 ///
1096 /// Like [`into_owned`](Self::into_owned), but takes `&self`:
1097 /// every borrowed text or byte string is copied, owned data is
1098 /// cloned, and the result borrows nothing from `self`. Use this
1099 /// when the original `Value` must remain accessible (for example
1100 /// it is held inside a larger structure); use
1101 /// [`into_owned`](Self::into_owned) when you can consume `self`
1102 /// and avoid the extra clones.
1103 ///
1104 /// The returned `Value<'b>` can be assigned to any lifetime,
1105 /// including `Value<'static>`.
1106 ///
1107 /// ```
1108 /// use cbor_core::Value;
1109 ///
1110 /// let bytes = b"\x65hello";
1111 /// let borrowed = Value::decode(bytes).unwrap();
1112 /// let owned: Value<'static> = borrowed.to_owned();
1113 /// assert_eq!(owned.as_str().unwrap(), "hello");
1114 /// // `borrowed` is still usable here.
1115 /// assert_eq!(borrowed.as_str().unwrap(), "hello");
1116 /// ```
1117 pub fn to_owned<'b>(&self) -> Value<'b> {
1118 match self {
1119 Self::SimpleValue(simple_value) => Value::SimpleValue(*simple_value),
1120 Self::Unsigned(x) => Value::Unsigned(*x),
1121 Self::Negative(x) => Value::Negative(*x),
1122 Self::Float(float) => Value::Float(*float),
1123 Self::ByteString(text) => Value::ByteString(text.clone().into_owned().into()),
1124 Self::TextString(bytes) => Value::TextString(bytes.clone().into_owned().into()),
1125 Self::Array(values) => Value::Array(values.iter().map(Value::to_owned).collect()),
1126 Self::Map(map) => Value::Map(map.iter().map(|(k, v)| (k.to_owned(), v.to_owned())).collect()),
1127 Self::Tag(tag, content) => Value::Tag(*tag, Box::new((**content).to_owned())),
1128 }
1129 }
1130
1131 /// Detach a `Value<'a>` from any borrow, consuming `self`.
1132 ///
1133 /// Walks the value recursively. Any borrowed text or byte string
1134 /// (`Cow::Borrowed` inside [`TextString`](Self::TextString) or
1135 /// [`ByteString`](Self::ByteString)) is copied into an owned
1136 /// allocation; already-owned strings, integers, floats, simple
1137 /// values, arrays, maps, and tags are moved through unchanged.
1138 /// The returned `Value<'b>` can be assigned to any lifetime,
1139 /// including `Value<'static>`, and no longer borrows from the
1140 /// original input slice.
1141 ///
1142 /// Use this when a value decoded from a slice needs to outlive
1143 /// that slice. If you only have a `&Value<'a>`, use
1144 /// [`to_owned`](Self::to_owned) instead.
1145 ///
1146 /// ```
1147 /// use cbor_core::Value;
1148 ///
1149 /// fn detach(bytes: &[u8]) -> Value<'static> {
1150 /// Value::decode(bytes).unwrap().into_owned()
1151 /// }
1152 ///
1153 /// let v = detach(b"\x65hello");
1154 /// assert_eq!(v.as_str().unwrap(), "hello");
1155 /// ```
1156 pub fn into_owned<'b>(self) -> Value<'b> {
1157 match self {
1158 Self::SimpleValue(simple_value) => Value::SimpleValue(simple_value),
1159 Self::Unsigned(x) => Value::Unsigned(x),
1160 Self::Negative(x) => Value::Negative(x),
1161 Self::Float(float) => Value::Float(float),
1162 Self::ByteString(text) => Value::ByteString(text.into_owned().into()),
1163 Self::TextString(bytes) => Value::TextString(bytes.into_owned().into()),
1164 Self::Array(values) => Value::Array(values.into_iter().map(Value::into_owned).collect()),
1165 Self::Map(map) => Value::Map(map.into_iter().map(|(k, v)| (k.into_owned(), v.into_owned())).collect()),
1166 Self::Tag(tag, content) => Value::Tag(tag, Box::new(content.into_owned())), // TODO: Replace with Box::map() once it is in stable
1167 }
1168 }
1169}
1170
1171/// Decoding and reading
1172impl<'a> Value<'a> {
1173 /// Decode a CBOR data item from binary bytes.
1174 ///
1175 /// Accepts any byte source by reference: `&[u8]`, `&[u8; N]`,
1176 /// `&Vec<u8>`, `&str`, `&String`, etc. Decoded text and byte
1177 /// strings borrow zero-copy from the input slice, so the returned
1178 /// [`Value`] inherits its lifetime: `Value::decode(&bytes)`
1179 /// produces `Value<'_>` tied to `bytes`. Reach for
1180 /// [`Value::read_from`](Self::read_from) when you need an
1181 /// owned `Value<'static>`.
1182 ///
1183 /// The input must contain **exactly one** CBOR item; any trailing
1184 /// bytes cause [`Error::InvalidFormat`](crate::Error::InvalidFormat).
1185 /// Use [`DecodeOptions::sequence_decoder`](crate::DecodeOptions::sequence_decoder)
1186 /// for CBOR sequences.
1187 ///
1188 /// Returns `Err` if the encoding is not canonical.
1189 ///
1190 /// ```
1191 /// use cbor_core::Value;
1192 /// let v = Value::decode(&[0x18, 42]).unwrap();
1193 /// assert_eq!(v.to_u32().unwrap(), 42);
1194 /// ```
1195 pub fn decode<T>(bytes: &'a T) -> crate::Result<Self>
1196 where
1197 T: AsRef<[u8]> + ?Sized,
1198 {
1199 crate::DecodeOptions::new().decode(bytes)
1200 }
1201
1202 /// Decode a CBOR data item from binary bytes into an owned [`Value`].
1203 ///
1204 /// Like [`decode`](Self::decode), but the result does not borrow
1205 /// from the input: text and byte strings are copied into owned
1206 /// allocations. Use this when the input is short-lived (a
1207 /// temporary buffer, a `Vec` returned from a function, etc.) and
1208 /// the decoded value needs to outlive it. The returned `Value`
1209 /// can be assigned to any lifetime, including `Value<'static>`.
1210 ///
1211 /// Equivalent to `Value::decode(bytes).map(Value::into_owned)`
1212 /// but more performant.
1213 ///
1214 /// ```
1215 /// use cbor_core::Value;
1216 ///
1217 /// fn decode_temp() -> Value<'static> {
1218 /// let buf: Vec<u8> = vec![0x65, b'h', b'e', b'l', b'l', b'o'];
1219 /// Value::decode_owned(&buf).unwrap()
1220 /// }
1221 ///
1222 /// assert_eq!(decode_temp().as_str().unwrap(), "hello");
1223 /// ```
1224 pub fn decode_owned(bytes: impl AsRef<[u8]>) -> crate::Result<Self> {
1225 crate::DecodeOptions::new().decode_owned(bytes)
1226 }
1227
1228 /// Decode a CBOR data item from hex-encoded bytes.
1229 ///
1230 /// Accepts any byte source (`&[u8]`, `&str`, `String`, `Vec<u8>`,
1231 /// etc.). Both uppercase and lowercase hex digits are accepted. The
1232 /// input must contain **exactly one** CBOR item; any trailing hex
1233 /// digits cause [`Error::InvalidFormat`](crate::Error::InvalidFormat).
1234 ///
1235 /// Hex decoding cannot borrow from the input (each pair of hex
1236 /// digits is converted into a single byte), so the returned value
1237 /// is always owned and may be stored as `Value<'static>`.
1238 ///
1239 /// Returns `Err` if the encoding is not canonical.
1240 ///
1241 /// ```
1242 /// use cbor_core::Value;
1243 /// let v = Value::decode_hex("182a").unwrap();
1244 /// assert_eq!(v.to_u32().unwrap(), 42);
1245 /// ```
1246 pub fn decode_hex(hex: impl AsRef<[u8]>) -> crate::Result<Self> {
1247 crate::DecodeOptions::new().format(crate::Format::Hex).decode_owned(hex)
1248 }
1249
1250 /// Read a single CBOR data item from a binary stream.
1251 ///
1252 /// The reader is advanced only to the end of the item; any further
1253 /// bytes remain in the stream, so repeated calls pull successive
1254 /// items of a CBOR sequence.
1255 ///
1256 /// Bytes are read into an internal buffer, so the result is
1257 /// always owned (it can be held as `Value<'static>`). For
1258 /// zero-copy decoding from a byte slice, use
1259 /// [`decode`](Self::decode) instead.
1260 ///
1261 /// ```
1262 /// use cbor_core::Value;
1263 /// let mut bytes: &[u8] = &[0x18, 42];
1264 /// let v = Value::read_from(&mut bytes).unwrap();
1265 /// assert_eq!(v.to_u32().unwrap(), 42);
1266 /// ```
1267 pub fn read_from(reader: impl std::io::Read) -> crate::IoResult<Self> {
1268 crate::DecodeOptions::new().read_from(reader)
1269 }
1270
1271 /// Read a single CBOR data item from a hex-encoded stream.
1272 ///
1273 /// Each byte of CBOR is expected as two hex digits (uppercase or
1274 /// lowercase). The reader is advanced only to the end of the item;
1275 /// any further hex digits remain in the stream, so repeated calls
1276 /// pull successive items of a CBOR sequence. The result is always
1277 /// owned.
1278 ///
1279 /// ```
1280 /// use cbor_core::Value;
1281 /// let mut hex = "182a".as_bytes();
1282 /// let v = Value::read_hex_from(&mut hex).unwrap();
1283 /// assert_eq!(v.to_u32().unwrap(), 42);
1284 /// ```
1285 pub fn read_hex_from(reader: impl std::io::Read) -> crate::IoResult<Self> {
1286 crate::DecodeOptions::new().format(crate::Format::Hex).read_from(reader)
1287 }
1288}
1289
1290/// Encoding and writing
1291impl<'a> Value<'a> {
1292 /// Encode this value to binary CBOR bytes.
1293 ///
1294 /// This is a convenience wrapper around [`write_to`](Self::write_to).
1295 ///
1296 /// ```
1297 /// use cbor_core::Value;
1298 /// let bytes = Value::from(42).encode();
1299 /// assert_eq!(bytes, [0x18, 42]);
1300 /// ```
1301 #[must_use]
1302 pub fn encode(&self) -> Vec<u8> {
1303 let len = self.encoded_len();
1304 let mut bytes = Vec::with_capacity(len);
1305 self.write_to(&mut bytes).unwrap();
1306 debug_assert_eq!(bytes.len(), len);
1307 bytes
1308 }
1309
1310 /// Encode this value to a hex-encoded CBOR string.
1311 ///
1312 /// This is a convenience wrapper around [`write_hex_to`](Self::write_hex_to).
1313 ///
1314 /// ```
1315 /// use cbor_core::Value;
1316 /// let hex = Value::from(42).encode_hex();
1317 /// assert_eq!(hex, "182a");
1318 /// ```
1319 #[must_use]
1320 pub fn encode_hex(&self) -> String {
1321 let len2 = self.encoded_len() * 2;
1322 let mut hex = Vec::with_capacity(len2);
1323 self.write_hex_to(&mut hex).unwrap();
1324 debug_assert_eq!(hex.len(), len2);
1325 String::from_utf8(hex).unwrap()
1326 }
1327
1328 /// Write this value as binary CBOR to a stream.
1329 ///
1330 /// ```
1331 /// use cbor_core::Value;
1332 /// let mut buf = Vec::new();
1333 /// Value::from(42).write_to(&mut buf).unwrap();
1334 /// assert_eq!(buf, [0x18, 42]);
1335 /// ```
1336 pub fn write_to(&self, mut writer: impl std::io::Write) -> std::io::Result<()> {
1337 self.do_write(&mut writer)
1338 }
1339
1340 /// Write this value as hex-encoded CBOR to a stream.
1341 ///
1342 /// Each binary byte is written as two lowercase hex digits. The
1343 /// adapter encodes on the fly without buffering the full output.
1344 ///
1345 /// ```
1346 /// use cbor_core::Value;
1347 /// let mut buf = Vec::new();
1348 /// Value::from(42).write_hex_to(&mut buf).unwrap();
1349 /// assert_eq!(buf, b"182a");
1350 /// ```
1351 pub fn write_hex_to(&self, writer: impl std::io::Write) -> std::io::Result<()> {
1352 struct HexWriter<W>(W);
1353
1354 impl<W: std::io::Write> std::io::Write for HexWriter<W> {
1355 fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
1356 for &byte in buf {
1357 write!(self.0, "{byte:02x}")?;
1358 }
1359 Ok(buf.len())
1360 }
1361 fn flush(&mut self) -> std::io::Result<()> {
1362 Ok(())
1363 }
1364 }
1365
1366 self.do_write(&mut HexWriter(writer))
1367 }
1368
1369 fn do_write(&self, writer: &mut impl std::io::Write) -> std::io::Result<()> {
1370 self.head().write_to(writer)?;
1371
1372 match self {
1373 Value::ByteString(bytes) => writer.write_all(bytes)?,
1374 Value::TextString(string) => writer.write_all(string.as_bytes())?,
1375
1376 Value::Tag(_number, content) => content.do_write(writer)?,
1377
1378 Value::Array(values) => {
1379 for value in values {
1380 value.do_write(writer)?;
1381 }
1382 }
1383
1384 Value::Map(map) => {
1385 for (key, value) in map {
1386 key.do_write(writer)?;
1387 value.do_write(writer)?;
1388 }
1389 }
1390
1391 _ => (),
1392 }
1393
1394 Ok(())
1395 }
1396
1397 pub(crate) fn encoded_len(&self) -> usize {
1398 self.head().encoded_len() + self.payload().encoded_len()
1399 }
1400}
1401
1402impl<'a> ValueView for Value<'a> {
1403 fn head(&self) -> Head {
1404 match self {
1405 Value::SimpleValue(sv) => Head::from_u64(Major::SimpleOrFloat, sv.0.into()),
1406 Value::Unsigned(n) => Head::from_u64(Major::Unsigned, *n),
1407 Value::Negative(n) => Head::from_u64(Major::Negative, *n),
1408 Value::Float(float) => float.head(),
1409 Value::ByteString(bytes) => Head::from_usize(Major::ByteString, bytes.len()),
1410 Value::TextString(text) => Head::from_usize(Major::TextString, text.len()),
1411 Value::Array(vec) => Head::from_usize(Major::Array, vec.len()),
1412 Value::Map(map) => Head::from_usize(Major::Map, map.len()),
1413 Value::Tag(number, _content) => Head::from_u64(Major::Tag, *number),
1414 }
1415 }
1416
1417 fn payload(&self) -> Payload<'_> {
1418 match self {
1419 Value::SimpleValue(_) | Value::Unsigned(_) | Value::Negative(_) | Value::Float(_) => Payload::None,
1420 Value::ByteString(bytes) => Payload::Bytes(bytes),
1421 Value::TextString(text) => Payload::Text(text),
1422 Value::Array(arr) => Payload::Array(arr),
1423 Value::Map(map) => Payload::Map(map),
1424 Value::Tag(_, content) => Payload::TagContent(content),
1425 }
1426 }
1427}
1428
1429/// Misc
1430impl<'a> Value<'a> {
1431 /// Classify this value by its [`DataType`].
1432 ///
1433 /// `DataType` is a flat enum with a variant per CBOR major type,
1434 /// plus a few promoted variants for tag/content combinations that
1435 /// carry well-known semantics:
1436 ///
1437 /// * Tag 0 wrapping a text string becomes
1438 /// [`DataType::DateTime`].
1439 /// * Tag 1 wrapping a numeric value becomes
1440 /// [`DataType::EpochTime`].
1441 /// * Tags 2 and 3 wrapping a byte string become
1442 /// [`DataType::BigInt`].
1443 ///
1444 /// Every other tag, including tag 0 over a non-text content or tag
1445 /// 2 over a non-bytes content, classifies as plain
1446 /// [`DataType::Tag`].
1447 ///
1448 /// Floats expose their precision: an f16 value reports
1449 /// [`DataType::Float16`], an f32 reports [`DataType::Float32`], and
1450 /// an f64 reports [`DataType::Float64`].
1451 ///
1452 /// The classification looks at structure only; it does not validate
1453 /// content. A [`DataType::DateTime`] value is "tag 0 wrapping
1454 /// text", not "a valid RFC 3339 timestamp"; full validation happens
1455 /// in the accessor methods. See [`DataType`] for the predicate
1456 /// helpers (`is_integer`, `is_numeric`, etc.) that group these
1457 /// variants by semantic role.
1458 ///
1459 /// ```
1460 /// use cbor_core::{DataType, Value};
1461 ///
1462 /// assert_eq!(Value::from(42).data_type(), DataType::Int);
1463 /// assert_eq!(Value::from("hi").data_type(), DataType::Text);
1464 /// assert_eq!(Value::from(3.14_f64).data_type(), DataType::Float64);
1465 /// assert_eq!(Value::null().data_type(), DataType::Null);
1466 ///
1467 /// // Tag 0 over a text string is recognised as a date/time.
1468 /// let dt = Value::tag(0, "2025-03-30T12:24:16Z");
1469 /// assert_eq!(dt.data_type(), DataType::DateTime);
1470 ///
1471 /// // Other tags fall through to plain Tag.
1472 /// let custom = Value::tag(1234, 0);
1473 /// assert_eq!(custom.data_type(), DataType::Tag);
1474 /// ```
1475 #[must_use]
1476 pub const fn data_type(&self) -> DataType {
1477 match self {
1478 Self::SimpleValue(sv) => sv.data_type(),
1479
1480 Self::Unsigned(_) | Self::Negative(_) => DataType::Int,
1481
1482 Self::Float(float) => float.data_type(),
1483
1484 Self::TextString(_) => DataType::Text,
1485 Self::ByteString(_) => DataType::Bytes,
1486
1487 Self::Array(_) => DataType::Array,
1488 Self::Map(_) => DataType::Map,
1489
1490 Self::Tag(tag::DATE_TIME, content) if content.data_type().is_text() => DataType::DateTime,
1491 Self::Tag(tag::EPOCH_TIME, content) if content.data_type().is_numeric() => DataType::EpochTime,
1492
1493 Self::Tag(tag::POS_BIG_INT | tag::NEG_BIG_INT, content) if content.data_type().is_bytes() => {
1494 DataType::BigInt
1495 }
1496
1497 Self::Tag(_, _) => DataType::Tag,
1498 }
1499 }
1500
1501 // Internal shortcut helper
1502 const fn is_bytes(&self) -> bool {
1503 self.data_type().is_bytes()
1504 }
1505
1506 /// Take the value out, leaving `null` in its place.
1507 ///
1508 /// ```
1509 /// use cbor_core::Value;
1510 ///
1511 /// let mut v = Value::from(42);
1512 /// let taken = v.take();
1513 /// assert_eq!(taken.to_u32().unwrap(), 42);
1514 /// assert!(v.data_type().is_null());
1515 /// ```
1516 pub fn take(&mut self) -> Self {
1517 std::mem::take(self)
1518 }
1519
1520 /// Replace the value, returning the old one.
1521 ///
1522 /// ```
1523 /// use cbor_core::Value;
1524 ///
1525 /// let mut v = Value::from("hello");
1526 /// let old = v.replace(Value::from("world"));
1527 /// assert_eq!(old.as_str().unwrap(), "hello");
1528 /// assert_eq!(v.as_str().unwrap(), "world");
1529 /// ```
1530 pub fn replace(&mut self, value: Self) -> Self {
1531 std::mem::replace(self, value)
1532 }
1533}
1534
1535/// Scalar accessors
1536impl<'a> Value<'a> {
1537 /// Extract a boolean. Returns `Err` for non-boolean values.
1538 pub const fn to_bool(&self) -> Result<bool> {
1539 match self {
1540 Self::SimpleValue(sv) => sv.to_bool(),
1541 Self::Tag(_number, content) => content.untagged().to_bool(),
1542 _ => Err(Error::IncompatibleType(self.data_type())),
1543 }
1544 }
1545
1546 /// Extract the raw simple value number (0-255, excluding 24-31).
1547 pub const fn to_simple_value(&self) -> Result<u8> {
1548 match self {
1549 Self::SimpleValue(sv) => Ok(sv.0),
1550 Self::Tag(_number, content) => content.untagged().to_simple_value(),
1551 _ => Err(Error::IncompatibleType(self.data_type())),
1552 }
1553 }
1554
1555 fn to_uint<T>(&self) -> Result<T>
1556 where
1557 T: TryFrom<u64> + TryFrom<u128>,
1558 {
1559 match self {
1560 Self::Unsigned(x) => T::try_from(*x).or(Err(Error::Overflow)),
1561 Self::Negative(_) => Err(Error::NegativeUnsigned),
1562
1563 Self::Tag(tag::POS_BIG_INT, content) if content.is_bytes() => {
1564 T::try_from(u128_from_slice(self.as_bytes()?)?).or(Err(Error::Overflow))
1565 }
1566
1567 Self::Tag(tag::NEG_BIG_INT, content) if content.is_bytes() => Err(Error::NegativeUnsigned),
1568 Self::Tag(_other_number, content) => content.peeled().to_uint(),
1569 _ => Err(Error::IncompatibleType(self.data_type())),
1570 }
1571 }
1572
1573 /// Narrow to `u8`. Returns `Err(Overflow)` or `Err(NegativeUnsigned)` on mismatch.
1574 pub fn to_u8(&self) -> Result<u8> {
1575 self.to_uint()
1576 }
1577
1578 /// Narrow to `u16`.
1579 pub fn to_u16(&self) -> Result<u16> {
1580 self.to_uint()
1581 }
1582
1583 /// Narrow to `u32`.
1584 pub fn to_u32(&self) -> Result<u32> {
1585 self.to_uint()
1586 }
1587
1588 /// Narrow to `u64`.
1589 pub fn to_u64(&self) -> Result<u64> {
1590 self.to_uint()
1591 }
1592
1593 /// Narrow to `u128`. Handles big integers (tag 2) transparently.
1594 pub fn to_u128(&self) -> Result<u128> {
1595 self.to_uint()
1596 }
1597
1598 /// Narrow to `usize`.
1599 pub fn to_usize(&self) -> Result<usize> {
1600 self.to_uint()
1601 }
1602
1603 #[allow(dead_code)]
1604 pub(crate) fn as_integer_bytes(&self) -> Result<IntegerBytes<'_>> {
1605 match self {
1606 Self::Unsigned(x) => Ok(IntegerBytes::UnsignedOwned(x.to_be_bytes())),
1607 Self::Negative(x) => Ok(IntegerBytes::NegativeOwned(x.to_be_bytes())),
1608
1609 Self::Tag(tag::POS_BIG_INT, content) if content.is_bytes() => {
1610 Ok(IntegerBytes::UnsignedBorrowed(content.as_bytes()?))
1611 }
1612
1613 Self::Tag(tag::NEG_BIG_INT, content) if content.is_bytes() => {
1614 Ok(IntegerBytes::NegativeBorrowed(content.as_bytes()?))
1615 }
1616
1617 Self::Tag(_other_number, content) => content.peeled().as_integer_bytes(),
1618 _ => Err(Error::IncompatibleType(self.data_type())),
1619 }
1620 }
1621
1622 fn to_sint<T>(&self) -> Result<T>
1623 where
1624 T: TryFrom<u64> + TryFrom<u128> + std::ops::Not<Output = T>,
1625 {
1626 match self {
1627 Self::Unsigned(x) => T::try_from(*x).or(Err(Error::Overflow)),
1628 Self::Negative(x) => T::try_from(*x).map(T::not).or(Err(Error::Overflow)),
1629
1630 Self::Tag(tag::POS_BIG_INT, content) if content.is_bytes() => {
1631 T::try_from(u128_from_slice(self.as_bytes()?)?).or(Err(Error::Overflow))
1632 }
1633
1634 Self::Tag(tag::NEG_BIG_INT, content) if content.is_bytes() => {
1635 T::try_from(u128_from_slice(self.as_bytes()?)?)
1636 .map(T::not)
1637 .or(Err(Error::Overflow))
1638 }
1639
1640 Self::Tag(_other_number, content) => content.peeled().to_sint(),
1641 _ => Err(Error::IncompatibleType(self.data_type())),
1642 }
1643 }
1644
1645 /// Narrow to `i8`.
1646 pub fn to_i8(&self) -> Result<i8> {
1647 self.to_sint()
1648 }
1649
1650 /// Narrow to `i16`.
1651 pub fn to_i16(&self) -> Result<i16> {
1652 self.to_sint()
1653 }
1654
1655 /// Narrow to `i32`.
1656 pub fn to_i32(&self) -> Result<i32> {
1657 self.to_sint()
1658 }
1659
1660 /// Narrow to `i64`.
1661 pub fn to_i64(&self) -> Result<i64> {
1662 self.to_sint()
1663 }
1664
1665 /// Narrow to `i128`. Handles big integers (tags 2 and 3) transparently.
1666 pub fn to_i128(&self) -> Result<i128> {
1667 self.to_sint()
1668 }
1669
1670 /// Narrow to `isize`.
1671 pub fn to_isize(&self) -> Result<isize> {
1672 self.to_sint()
1673 }
1674
1675 /// Convert to `f32`.
1676 ///
1677 /// Returns `Err(Precision)` for f64-width values.
1678 pub fn to_f32(&self) -> Result<f32> {
1679 match self {
1680 Self::Float(float) => float.to_f32(),
1681 Self::Tag(_number, content) => content.untagged().to_f32(),
1682 _ => Err(Error::IncompatibleType(self.data_type())),
1683 }
1684 }
1685
1686 /// Convert to `f64`.
1687 ///
1688 /// Always succeeds for float values.
1689 pub fn to_f64(&self) -> Result<f64> {
1690 match self {
1691 Self::Float(float) => Ok(float.to_f64()),
1692 Self::Tag(_number, content) => content.untagged().to_f64(),
1693 _ => Err(Error::IncompatibleType(self.data_type())),
1694 }
1695 }
1696
1697 /// Convert a time value to [`SystemTime`].
1698 ///
1699 /// Accepts date/time strings (tag 0), epoch time values (tag 1),
1700 /// and untagged integers or floats. Numeric values must be
1701 /// non-negative and in the range 0 to 253402300799. Date/time
1702 /// strings may include a timezone offset, which is converted to
1703 /// UTC.
1704 ///
1705 /// Returns [`Err(IncompatibleType)`](Error::IncompatibleType) for
1706 /// values that are neither numeric nor text, [`Err(InvalidValue)`](Error::InvalidValue)
1707 /// if a numeric value is out of range, and [`Err(InvalidFormat)`](Error::InvalidFormat)
1708 /// if a text string is not a valid RFC 3339 timestamp. Leap seconds (`:60`) are rejected
1709 /// because [`SystemTime`] cannot represent them.
1710 ///
1711 /// ```
1712 /// use std::time::{Duration, UNIX_EPOCH};
1713 /// use cbor_core::Value;
1714 ///
1715 /// let v = Value::tag(1, 1_000_000);
1716 /// let t = v.to_system_time().unwrap();
1717 /// assert_eq!(t, UNIX_EPOCH + Duration::from_secs(1_000_000));
1718 /// ```
1719 pub fn to_system_time(&self) -> Result<SystemTime> {
1720 if let Ok(s) = self.as_str() {
1721 Ok(s.parse::<crate::iso3339::Timestamp>()?.try_into()?)
1722 } else if let Ok(f) = self.to_f64() {
1723 if f.is_finite() && (0.0..=253402300799.0).contains(&f) {
1724 Ok(SystemTime::UNIX_EPOCH + Duration::from_secs_f64(f))
1725 } else {
1726 Err(Error::InvalidValue)
1727 }
1728 } else {
1729 match self.to_u64() {
1730 Ok(secs) if secs <= 253402300799 => Ok(SystemTime::UNIX_EPOCH + Duration::from_secs(secs)),
1731 Ok(_) | Err(Error::NegativeUnsigned) => Err(Error::InvalidValue),
1732 Err(error) => Err(error),
1733 }
1734 }
1735 }
1736}
1737
1738/// Bytes and text strings
1739impl<'a> Value<'a> {
1740 /// Borrow the byte string as a slice.
1741 pub fn as_bytes(&self) -> Result<&[u8]> {
1742 match self {
1743 Self::ByteString(bytes) => Ok(bytes.as_ref()),
1744 Self::Tag(_number, content) => content.untagged().as_bytes(),
1745 _ => Err(Error::IncompatibleType(self.data_type())),
1746 }
1747 }
1748
1749 /// Borrow the byte string as a mutable `Vec`.
1750 pub fn as_bytes_mut(&mut self) -> Result<&mut Vec<u8>> {
1751 match self {
1752 Self::ByteString(bytes) => Ok(bytes.to_mut()),
1753 Self::Tag(_number, content) => content.untagged_mut().as_bytes_mut(),
1754 _ => Err(Error::IncompatibleType(self.data_type())),
1755 }
1756 }
1757
1758 /// Take ownership of the byte string.
1759 pub fn into_bytes(self) -> Result<Vec<u8>> {
1760 match self {
1761 Self::ByteString(bytes) => Ok(bytes.into_owned()),
1762 Self::Tag(_number, content) => content.into_untagged().into_bytes(),
1763 _ => Err(Error::IncompatibleType(self.data_type())),
1764 }
1765 }
1766
1767 /// Borrow the text string as a `&str`.
1768 pub fn as_str(&self) -> Result<&str> {
1769 match self {
1770 Self::TextString(s) => Ok(s.as_ref()),
1771 Self::Tag(_number, content) => content.untagged().as_str(),
1772 _ => Err(Error::IncompatibleType(self.data_type())),
1773 }
1774 }
1775
1776 /// Borrow the text string as a mutable `String`.
1777 pub fn as_string_mut(&mut self) -> Result<&mut String> {
1778 match self {
1779 Self::TextString(s) => Ok(s.to_mut()),
1780 Self::Tag(_number, content) => content.untagged_mut().as_string_mut(),
1781 _ => Err(Error::IncompatibleType(self.data_type())),
1782 }
1783 }
1784
1785 /// Take ownership of the text string.
1786 pub fn into_string(self) -> Result<String> {
1787 match self {
1788 Self::TextString(s) => Ok(s.into_owned()),
1789 Self::Tag(_number, content) => content.into_untagged().into_string(),
1790 _ => Err(Error::IncompatibleType(self.data_type())),
1791 }
1792 }
1793}
1794
1795/// Arrays and maps
1796impl<'a> Value<'a> {
1797 /// Borrow the array elements as a slice.
1798 pub fn as_array(&self) -> Result<&[Value<'a>]> {
1799 match self {
1800 Self::Array(v) => Ok(v.as_slice()),
1801 Self::Tag(_number, content) => content.untagged().as_array(),
1802 _ => Err(Error::IncompatibleType(self.data_type())),
1803 }
1804 }
1805
1806 /// Borrow the array as a mutable `Vec`.
1807 pub const fn as_array_mut(&mut self) -> Result<&mut Vec<Value<'a>>> {
1808 match self {
1809 Self::Array(v) => Ok(v),
1810 Self::Tag(_number, content) => content.untagged_mut().as_array_mut(),
1811 _ => Err(Error::IncompatibleType(self.data_type())),
1812 }
1813 }
1814
1815 /// Take ownership of the array.
1816 pub fn into_array(self) -> Result<Vec<Value<'a>>> {
1817 match self {
1818 Self::Array(v) => Ok(v),
1819 Self::Tag(_number, content) => content.into_untagged().into_array(),
1820 _ => Err(Error::IncompatibleType(self.data_type())),
1821 }
1822 }
1823
1824 /// Borrow the map.
1825 pub const fn as_map(&self) -> Result<&BTreeMap<Value<'a>, Value<'a>>> {
1826 match self {
1827 Self::Map(m) => Ok(m),
1828 Self::Tag(_number, content) => content.untagged().as_map(),
1829 _ => Err(Error::IncompatibleType(self.data_type())),
1830 }
1831 }
1832
1833 /// Borrow the map mutably.
1834 pub const fn as_map_mut(&mut self) -> Result<&mut BTreeMap<Value<'a>, Value<'a>>> {
1835 match self {
1836 Self::Map(m) => Ok(m),
1837 Self::Tag(_number, content) => content.untagged_mut().as_map_mut(),
1838 _ => Err(Error::IncompatibleType(self.data_type())),
1839 }
1840 }
1841
1842 /// Take ownership of the map.
1843 pub fn into_map(self) -> Result<BTreeMap<Value<'a>, Value<'a>>> {
1844 match self {
1845 Self::Map(m) => Ok(m),
1846 Self::Tag(_number, content) => content.into_untagged().into_map(),
1847 _ => Err(Error::IncompatibleType(self.data_type())),
1848 }
1849 }
1850}
1851
1852/// Array and map helpers
1853impl<'a> Value<'a> {
1854 /// Look up an element by index (arrays) or key (maps).
1855 ///
1856 /// Accepts anything convertible into [`ValueKey`](crate::ValueKey):
1857 /// integers for array indices, and `&str`, `&[u8]`, integers, `&Value`,
1858 /// etc. for map keys. Transparent through tags.
1859 ///
1860 /// Returns `None` if the value is not an array or map, the index is
1861 /// out of bounds, the key is missing, or the key type does not match
1862 /// the collection (e.g. a string index into an array).
1863 ///
1864 /// ```
1865 /// use cbor_core::{Value, array, map};
1866 ///
1867 /// let a = array![10, 20, 30];
1868 /// assert_eq!(a.get(1).unwrap().to_u32().unwrap(), 20);
1869 /// assert!(a.get(5).is_none());
1870 ///
1871 /// let m = map! { "x" => 10 };
1872 /// assert_eq!(m.get("x").unwrap().to_u32().unwrap(), 10);
1873 /// assert!(m.get("missing").is_none());
1874 /// ```
1875 pub fn get<'k>(&self, index: impl Into<crate::ValueKey<'k>>) -> Option<&Value<'a>> {
1876 let key = index.into();
1877 match self.untagged() {
1878 Value::Array(arr) => key.to_usize().and_then(|idx| arr.get(idx)),
1879 Value::Map(map) => map.get(&key as &dyn ValueView),
1880 _ => None,
1881 }
1882 }
1883
1884 /// Mutable version of [`get`](Self::get).
1885 ///
1886 /// ```
1887 /// use cbor_core::{Value, array};
1888 ///
1889 /// let mut a = array![10, 20, 30];
1890 /// *a.get_mut(1).unwrap() = Value::from(99);
1891 /// assert_eq!(a[1].to_u32().unwrap(), 99);
1892 /// ```
1893 pub fn get_mut<'k>(&mut self, index: impl Into<crate::ValueKey<'k>>) -> Option<&mut Value<'a>> {
1894 let key = index.into();
1895 match self.untagged_mut() {
1896 Value::Array(arr) => key.to_usize().and_then(|idx| arr.get_mut(idx)),
1897 Value::Map(map) => map.get_mut(&key as &dyn ValueView),
1898 _ => None,
1899 }
1900 }
1901
1902 /// Remove and return an element by index (arrays) or key (maps).
1903 ///
1904 /// For **arrays**, shifts subsequent elements down like
1905 /// [`Vec::remove`] (O(n)) and returns the removed element. The key
1906 /// must be a valid `usize` index in range `0..len`; otherwise this
1907 /// method **panics**, matching [`Vec::remove`] and the indexing
1908 /// operator `v[i]`.
1909 ///
1910 /// For **maps**, removes and returns the entry for the given key,
1911 /// or `None` if the key is missing — matching [`BTreeMap::remove`].
1912 ///
1913 /// Transparent through tags, matching [`get`](Self::get).
1914 ///
1915 /// # Panics
1916 ///
1917 /// - If the value is not an array or map.
1918 /// - If the value is an array and the key is not a valid `usize`
1919 /// index in range `0..len`.
1920 ///
1921 /// ```
1922 /// use cbor_core::{array, map};
1923 ///
1924 /// let mut a = array![10, 20, 30];
1925 /// assert_eq!(a.remove(1).unwrap().to_u32().unwrap(), 20);
1926 /// assert_eq!(a.len().unwrap(), 2);
1927 ///
1928 /// let mut m = map! { "x" => 10, "y" => 20 };
1929 /// assert_eq!(m.remove("x").unwrap().to_u32().unwrap(), 10);
1930 /// assert!(m.remove("missing").is_none());
1931 /// ```
1932 ///
1933 /// [`BTreeMap::remove`]: std::collections::BTreeMap::remove
1934 pub fn remove<'k>(&mut self, index: impl Into<crate::ValueKey<'k>>) -> Option<Value<'a>> {
1935 let key = index.into();
1936 match self.untagged_mut() {
1937 Value::Array(arr) => {
1938 let idx = key.to_usize().expect("array index must be a non-negative integer");
1939 assert!(idx < arr.len(), "array index {idx} out of bounds (len {})", arr.len());
1940 Some(arr.remove(idx))
1941 }
1942 Value::Map(map) => map.remove(&key as &dyn ValueView),
1943 other => panic!("remove called on {:?}, expected array or map", other.data_type()),
1944 }
1945 }
1946
1947 /// Insert an element into a map or array.
1948 ///
1949 /// For **maps**, behaves like [`BTreeMap::insert`]: inserts the
1950 /// key/value pair and returns the previous value if the key was
1951 /// already present, otherwise `None`.
1952 ///
1953 /// For **arrays**, the key is a `usize` index in range `0..=len`.
1954 /// The value is inserted at that position, shifting subsequent
1955 /// elements right like [`Vec::insert`] (O(n)). Insertion into an
1956 /// array **always returns `None`**.
1957 ///
1958 /// Transparent through tags.
1959 ///
1960 /// # Panics
1961 ///
1962 /// - If the value is not an array or map.
1963 /// - If the value is an array and the key is not a valid `usize`
1964 /// index in range `0..=len`.
1965 ///
1966 /// ```
1967 /// use cbor_core::{array, map};
1968 ///
1969 /// let mut m = map! { "x" => 10 };
1970 /// assert_eq!(m.insert("y", 20), None);
1971 /// assert_eq!(m.insert("x", 99).unwrap().to_u32().unwrap(), 10);
1972 /// assert_eq!(m["x"].to_u32().unwrap(), 99);
1973 ///
1974 /// let mut a = array![10, 30];
1975 /// assert_eq!(a.insert(1, 20), None); // always None for arrays
1976 /// assert_eq!(a[1].to_u32().unwrap(), 20);
1977 /// assert_eq!(a.len().unwrap(), 3);
1978 /// ```
1979 ///
1980 /// [`BTreeMap::insert`]: std::collections::BTreeMap::insert
1981 pub fn insert(&mut self, key: impl Into<Value<'a>>, value: impl Into<Value<'a>>) -> Option<Value<'a>> {
1982 let key = key.into();
1983 let value = value.into();
1984 match self.untagged_mut() {
1985 Value::Array(arr) => {
1986 let idx = key.to_usize().expect("array index must be a non-negative integer");
1987 assert!(idx <= arr.len(), "array index {idx} out of bounds (len {})", arr.len());
1988 arr.insert(idx, value);
1989 None
1990 }
1991 Value::Map(map) => map.insert(key, value),
1992 other => panic!("insert called on {:?}, expected array or map", other.data_type()),
1993 }
1994 }
1995
1996 /// Append a value to the end of an array (O(1)), like [`Vec::push`].
1997 ///
1998 /// Transparent through tags.
1999 ///
2000 /// # Panics
2001 ///
2002 /// If the value is not an array.
2003 ///
2004 /// ```
2005 /// use cbor_core::array;
2006 ///
2007 /// let mut a = array![1, 2];
2008 /// a.append(3);
2009 /// a.append(4);
2010 /// assert_eq!(a.len().unwrap(), 4);
2011 /// assert_eq!(a[3].to_u32().unwrap(), 4);
2012 /// ```
2013 pub fn append(&mut self, value: impl Into<Value<'a>>) {
2014 match self.untagged_mut() {
2015 Value::Array(arr) => arr.push(value.into()),
2016 other => panic!("append called on {:?}, expected array", other.data_type()),
2017 }
2018 }
2019
2020 /// Test whether an array contains an index or a map contains a key.
2021 ///
2022 /// For **arrays**, returns `true` if the key converts to a `usize`
2023 /// in range `0..len`. For **maps**, returns `true` if the key is
2024 /// present. All other types return `false`. Transparent through tags.
2025 ///
2026 /// ```
2027 /// use cbor_core::{Value, array, map};
2028 ///
2029 /// let a = array![10, 20, 30];
2030 /// assert!(a.contains(1));
2031 /// assert!(!a.contains(5));
2032 ///
2033 /// let m = map! { "x" => 10 };
2034 /// assert!(m.contains("x"));
2035 /// assert!(!m.contains("missing"));
2036 ///
2037 /// assert!(!Value::from(42).contains(0));
2038 /// ```
2039 pub fn contains<'k>(&self, key: impl Into<crate::ValueKey<'k>>) -> bool {
2040 let key = key.into();
2041 match self.untagged() {
2042 Value::Array(arr) => key.to_usize().is_some_and(|idx| idx < arr.len()),
2043 Value::Map(map) => map.contains_key(&key as &dyn ValueView),
2044 _ => false,
2045 }
2046 }
2047
2048 /// Number of elements in an array or map, or `None` for any other type.
2049 ///
2050 /// Transparent through tags. For text and byte strings, use
2051 /// [`as_str`](Self::as_str) or [`as_bytes`](Self::as_bytes) and call
2052 /// `len()` on the slice.
2053 ///
2054 /// ```
2055 /// use cbor_core::{Value, array, map};
2056 ///
2057 /// assert_eq!(array![1, 2, 3].len(), Some(3));
2058 /// assert_eq!(map! { "x" => 1, "y" => 2 }.len(), Some(2));
2059 /// assert_eq!(Value::from("hello").len(), None);
2060 /// assert_eq!(Value::from(42).len(), None);
2061 /// ```
2062 #[allow(clippy::len_without_is_empty)]
2063 pub fn len(&self) -> Option<usize> {
2064 match self.untagged() {
2065 Value::Array(arr) => Some(arr.len()),
2066 Value::Map(map) => Some(map.len()),
2067 _ => None,
2068 }
2069 }
2070}
2071
2072/// Tags
2073impl<'a> Value<'a> {
2074 /// Return the tag number.
2075 pub const fn tag_number(&self) -> Result<u64> {
2076 match self {
2077 Self::Tag(number, _content) => Ok(*number),
2078 _ => Err(Error::IncompatibleType(self.data_type())),
2079 }
2080 }
2081
2082 /// Borrow the tag content.
2083 pub const fn tag_content(&self) -> Result<&Self> {
2084 match self {
2085 Self::Tag(_tag, content) => Ok(content),
2086 _ => Err(Error::IncompatibleType(self.data_type())),
2087 }
2088 }
2089
2090 /// Mutably borrow the tag content.
2091 pub const fn tag_content_mut(&mut self) -> Result<&mut Self> {
2092 match self {
2093 Self::Tag(_, value) => Ok(value),
2094 _ => Err(Error::IncompatibleType(self.data_type())),
2095 }
2096 }
2097
2098 /// Borrow tag number and content together.
2099 pub fn as_tag(&self) -> Result<(u64, &Value<'a>)> {
2100 match self {
2101 Self::Tag(number, content) => Ok((*number, content)),
2102 _ => Err(Error::IncompatibleType(self.data_type())),
2103 }
2104 }
2105
2106 /// Borrow tag number and mutable content together.
2107 pub fn as_tag_mut(&mut self) -> Result<(u64, &mut Value<'a>)> {
2108 match self {
2109 Self::Tag(number, content) => Ok((*number, content)),
2110 _ => Err(Error::IncompatibleType(self.data_type())),
2111 }
2112 }
2113
2114 /// Consume self and return tag number and content.
2115 pub fn into_tag(self) -> Result<(u64, Value<'a>)> {
2116 match self {
2117 Self::Tag(number, content) => Ok((number, *content)),
2118 _ => Err(Error::IncompatibleType(self.data_type())),
2119 }
2120 }
2121
2122 /// Remove the outermost tag, returning its number. Returns `None` if
2123 /// the value is not tagged.
2124 pub fn remove_tag(&mut self) -> Option<u64> {
2125 let mut result = None;
2126 if let Self::Tag(number, content) = self {
2127 result = Some(*number);
2128 *self = std::mem::take(content);
2129 }
2130 result
2131 }
2132
2133 /// Remove all nested tags, returning their numbers from outermost to
2134 /// innermost.
2135 pub fn remove_all_tags(&mut self) -> Vec<u64> {
2136 let mut tags = Vec::new();
2137 while let Self::Tag(number, content) = self {
2138 tags.push(*number);
2139 *self = std::mem::take(content);
2140 }
2141 tags
2142 }
2143
2144 /// Skip all tag wrappers except the innermost one.
2145 /// Returns `self` unchanged if not tagged or only single-tagged.
2146 #[must_use]
2147 pub(crate) const fn peeled(&self) -> &Self {
2148 let mut result = self;
2149 while let Self::Tag(_, content) = result
2150 && content.data_type().is_tag()
2151 {
2152 result = content;
2153 }
2154 result
2155 }
2156
2157 /// Borrow the innermost non-tag value, skipping all tag wrappers.
2158 #[must_use]
2159 pub const fn untagged(&self) -> &Self {
2160 let mut result = self;
2161 while let Self::Tag(_, content) = result {
2162 result = content;
2163 }
2164 result
2165 }
2166
2167 /// Mutable version of [`untagged`](Self::untagged).
2168 pub const fn untagged_mut(&mut self) -> &mut Self {
2169 let mut result = self;
2170 while let Self::Tag(_, content) = result {
2171 result = content;
2172 }
2173 result
2174 }
2175
2176 /// Consuming version of [`untagged`](Self::untagged).
2177 #[must_use]
2178 pub fn into_untagged(mut self) -> Self {
2179 while let Self::Tag(_number, content) = self {
2180 self = *content;
2181 }
2182 self
2183 }
2184}