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