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