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}