Skip to main content

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