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