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