Skip to main content

cbor_core/
value.rs

1mod array;
2mod bytes;
3mod default_eq_ord_hash;
4mod float;
5mod index;
6mod int;
7mod map;
8mod simple_value;
9mod string;
10
11use std::{
12    cmp,
13    collections::BTreeMap,
14    fmt,
15    hash::{Hash, Hasher},
16    io,
17    ops::{Index, IndexMut},
18    time::{Duration, SystemTime},
19};
20
21use crate::{
22    ArgLength, Array, CtrlByte, DataType, DateTime, EpochTime, Error, Float, IntegerBytes, Major, Map, Result,
23    SimpleValue, Tag, util::u128_from_slice,
24};
25
26const OOM_MITIGATION: usize = 100_000_000; // maximum size to reserve capacity
27const LENGTH_LIMIT: u64 = 1_000_000_000; // length limit for arrays, maps, test and byte strings
28const RECURSION_LIMIT: u16 = 200; // maximum hierarchical data structure depth
29
30/// A single CBOR data item.
31///
32/// `Value` covers all CBOR major types: integers, floats, byte and text
33/// strings, arrays, maps, tagged values, and simple values (null, booleans).
34/// It encodes deterministically and decodes only canonical input.
35///
36/// # Creating values
37///
38/// Rust primitives convert via [`From`]:
39///
40/// ```
41/// use cbor_core::Value;
42///
43/// let n = Value::from(42);
44/// let s = Value::from("hello");
45/// let b = Value::from(true);
46/// ```
47///
48/// For arrays and maps the `array!` and `map!` macros are convenient:
49///
50/// ```
51/// use cbor_core::{Value, array, map};
52///
53/// let a = array![1, 2, 3];
54/// let m = map! { "x" => 10, "y" => 20 };
55/// ```
56///
57/// Arrays and maps can also be built from standard Rust collections.
58/// Slices, `Vec`s, fixed-size arrays, `BTreeMap`s, `HashMap`s, and
59/// slices of key-value pairs all convert automatically:
60///
61/// ```
62/// use cbor_core::Value;
63/// use std::collections::HashMap;
64///
65/// // Array from a slice
66/// let a = Value::array([1, 2, 3].as_slice());
67///
68/// // Map from a HashMap
69/// let mut hm = HashMap::new();
70/// hm.insert(1, 2);
71/// let m = Value::map(&hm);
72///
73/// // Map from key-value pairs
74/// let m = Value::map([("x", 10), ("y", 20)]);
75/// ```
76///
77/// Use `()` to create empty arrays or maps without spelling out a type:
78///
79/// ```
80/// use cbor_core::Value;
81///
82/// let empty_array = Value::array(());
83/// let empty_map = Value::map(());
84///
85/// assert_eq!(empty_array.as_array().unwrap().len(), 0);
86/// assert_eq!(empty_map.as_map().unwrap().len(), 0);
87/// ```
88///
89/// Named constructors are available for cases where `From` is ambiguous:
90///
91/// | Constructor | Builds |
92/// |---|---|
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::array(v)`](Value::array) | Array from slice, `Vec`, or fixed-size array |
97/// | [`Value::map(v)`](Value::map) | Map from `BTreeMap`, `HashMap`, slice of pairs, etc. |
98/// | [`Value::tag(n, v)`](Value::tag) | Tagged value |
99///
100/// # Encoding and decoding
101///
102/// ```
103/// use cbor_core::Value;
104///
105/// let original = Value::from(-1000);
106/// let bytes = original.encode();
107/// let decoded = Value::decode(&bytes).unwrap();
108/// assert_eq!(original, decoded);
109/// ```
110///
111/// For streaming use, [`write_to`](Value::write_to) and
112/// [`read_from`](Value::read_from) operate on any `io::Write` / `io::Read`.
113///
114/// # Accessors
115///
116/// Accessor methods extract or borrow the inner data of each variant.
117/// All return `Result<T>`, yielding `Err(Error::IncompatibleType)` on a
118/// type mismatch. The naming follows Rust conventions:
119///
120/// | Prefix | Meaning | Returns |
121/// |---|---|---|
122/// | `as_*` | Borrow inner data | `&T` or `&mut T` (with `_mut`) |
123/// | `to_*` | Convert or narrow | Owned `Copy` type (`u8`, `f32`, ...) |
124/// | `into_*` | Consume self, extract | Owned `T` |
125/// | no prefix | Trivial property | `Copy` scalar |
126///
127/// ## Simple values
128///
129/// In CBOR, booleans and null are not distinct types but specific simple
130/// values: `false` is 20, `true` is 21, `null` is 22. This means a
131/// boolean value is always also a simple value. [`to_bool`](Self::to_bool)
132/// provides typed access to `true`/`false`, while
133/// [`to_simple_value`](Self::to_simple_value) works on any simple value
134/// including booleans and null.
135///
136/// | Method | Returns | Notes |
137/// |---|---|---|
138/// | [`to_simple_value`](Self::to_simple_value) | `Result<u8>` | Raw simple value number |
139/// | [`to_bool`](Self::to_bool) | `Result<bool>` | Only for `true`/`false` |
140///
141/// ```
142/// use cbor_core::Value;
143///
144/// let v = Value::from(true);
145/// assert_eq!(v.to_bool().unwrap(), true);
146/// assert_eq!(v.to_simple_value().unwrap(), 21); // CBOR true = simple(21)
147///
148/// // null is also a simple value
149/// let n = Value::null();
150/// assert!(n.to_bool().is_err());              // not a boolean
151/// assert_eq!(n.to_simple_value().unwrap(), 22); // but is simple(22)
152/// ```
153///
154/// ## Integers
155///
156/// CBOR has effectively four integer types (unsigned or negative, and
157/// normal or big integer) with different internal representations.
158/// This is handled transparently by the API.
159///
160/// The `to_*` accessors perform checked
161/// narrowing into any Rust integer type, returning `Err(Overflow)` if
162/// the value does not fit, or `Err(NegativeUnsigned)` when extracting a
163/// negative value into an unsigned type.
164///
165/// | Method | Returns |
166/// |---|---|
167/// | [`to_u8`](Self::to_u8) .. [`to_u128`](Self::to_u128), [`to_usize`](Self::to_usize) | `Result<uN>` |
168/// | [`to_i8`](Self::to_i8) .. [`to_i128`](Self::to_i128), [`to_isize`](Self::to_isize) | `Result<iN>` |
169///
170/// ```
171/// use cbor_core::Value;
172///
173/// let v = Value::from(1000);
174/// assert_eq!(v.to_u32().unwrap(), 1000);
175/// assert_eq!(v.to_i64().unwrap(), 1000);
176/// assert!(v.to_u8().is_err()); // overflow
177///
178/// let neg = Value::from(-5);
179/// assert_eq!(neg.to_i8().unwrap(), -5);
180/// assert!(neg.to_u32().is_err()); // negative unsigned
181/// ```
182///
183/// ## Floats
184///
185/// Floats are stored internally in their shortest CBOR encoding (`f16`,
186/// `f32`, or `f64`). [`to_f64`](Self::to_f64) always succeeds since every
187/// float can widen to `f64`. [`to_f32`](Self::to_f32) fails with
188/// `Err(Precision)` if the value is stored as `f64`.
189/// A float internally stored as `f16` can always be converted to either
190/// an `f32` or `f64` for obvious reasons.
191///
192/// | Method | Returns |
193/// |---|---|
194/// | [`to_f32`](Self::to_f32) | `Result<f32>` (fails for f64 values) |
195/// | [`to_f64`](Self::to_f64) | `Result<f64>` |
196///
197/// ```
198/// use cbor_core::Value;
199///
200/// let v = Value::from(2.5);
201/// assert_eq!(v.to_f64().unwrap(), 2.5);
202/// assert_eq!(v.to_f32().unwrap(), 2.5);
203/// ```
204///
205/// ## Byte strings
206///
207/// Byte strings are stored as `Vec<u8>`. Use [`as_bytes`](Self::as_bytes)
208/// for a borrowed slice, or [`into_bytes`](Self::into_bytes) to take
209/// ownership without copying.
210///
211/// | Method | Returns |
212/// |---|---|
213/// | [`as_bytes`](Self::as_bytes) | `Result<&[u8]>` |
214/// | [`as_bytes_mut`](Self::as_bytes_mut) | `Result<&mut Vec<u8>>` |
215/// | [`into_bytes`](Self::into_bytes) | `Result<Vec<u8>>` |
216///
217/// ```
218/// use cbor_core::Value;
219///
220/// let mut v = Value::from(vec![1, 2, 3]);
221/// v.as_bytes_mut().unwrap().push(4);
222/// assert_eq!(v.as_bytes().unwrap(), &[1, 2, 3, 4]);
223/// ```
224///
225/// ## Text strings
226///
227/// Text strings are stored as `String` (guaranteed valid UTF-8 by the
228/// decoder). Use [`as_str`](Self::as_str) for a borrowed `&str`, or
229/// [`into_string`](Self::into_string) to take ownership.
230///
231/// | Method | Returns |
232/// |---|---|
233/// | [`as_str`](Self::as_str) | `Result<&str>` |
234/// | [`as_string_mut`](Self::as_string_mut) | `Result<&mut String>` |
235/// | [`into_string`](Self::into_string) | `Result<String>` |
236///
237/// ```
238/// use cbor_core::Value;
239///
240/// let v = Value::from("hello");
241/// assert_eq!(v.as_str().unwrap(), "hello");
242///
243/// // Modify in place
244/// let mut v = Value::from("hello");
245/// v.as_string_mut().unwrap().push_str(" world");
246/// assert_eq!(v.as_str().unwrap(), "hello world");
247/// ```
248///
249/// ## Arrays
250///
251/// Arrays are stored as `Vec<Value>`. Use [`as_array`](Self::as_array)
252/// to borrow the elements as a slice, or [`as_array_mut`](Self::as_array_mut)
253/// to modify them in place.
254///
255/// | Method | Returns |
256/// |---|---|
257/// | [`as_array`](Self::as_array) | `Result<&[Value]>` |
258/// | [`as_array_mut`](Self::as_array_mut) | `Result<&mut Vec<Value>>` |
259/// | [`into_array`](Self::into_array) | `Result<Vec<Value>>` |
260///
261/// ```
262/// use cbor_core::{Value, array};
263///
264/// let v = array![10, 20, 30];
265/// let items = v.as_array().unwrap();
266/// assert_eq!(items[1].to_u32().unwrap(), 20);
267///
268/// // Modify in place
269/// let mut v = array![1, 2];
270/// v.as_array_mut().unwrap().push(3.into());
271/// assert_eq!(v.as_array().unwrap().len(), 3);
272/// ```
273///
274/// ## Maps
275///
276/// Maps are stored as `BTreeMap<Value, Value>`, giving canonical key
277/// order. Use standard `BTreeMap` methods on the result of
278/// [`as_map`](Self::as_map) to look up entries.
279///
280/// | Method | Returns |
281/// |---|---|
282/// | [`as_map`](Self::as_map) | `Result<&BTreeMap<Value, Value>>` |
283/// | [`as_map_mut`](Self::as_map_mut) | `Result<&mut BTreeMap<Value, Value>>` |
284/// | [`into_map`](Self::into_map) | `Result<BTreeMap<Value, Value>>` |
285///
286/// ```
287/// use cbor_core::{Value, map};
288///
289/// let v = map! { "name" => "Alice", "age" => 30 };
290/// assert_eq!(v["name"].as_str().unwrap(), "Alice");
291///
292/// // Modify in place
293/// let mut v = map! { "count" => 1 };
294/// v.as_map_mut().unwrap().insert("count".into(), 2.into());
295/// assert_eq!(v["count"].to_u32().unwrap(), 2);
296/// ```
297///
298/// ## Indexing
299///
300/// Arrays and maps support `Index` and `IndexMut` with any type that
301/// converts into `Value`. For arrays the index is converted to `usize`;
302/// for maps it is used as a key lookup. Panics on type mismatch or
303/// missing key, just like `Vec` and `BTreeMap`.
304///
305/// ```
306/// use cbor_core::{Value, array, map};
307///
308/// let a = array![10, 20, 30];
309/// assert_eq!(a[1].to_u32().unwrap(), 20);
310///
311/// let m = map! { "x" => 10, "y" => 20 };
312/// assert_eq!(m["x"].to_u32().unwrap(), 10);
313/// ```
314///
315/// ## Tags
316///
317/// A tag wraps another value with a numeric label (e.g. tag 1 for epoch
318/// timestamps, tag 32 for URIs). Tags can be nested.
319///
320/// | Method | Returns | Notes |
321/// |---|---|---|
322/// | [`tag_number`](Self::tag_number) | `Result<u64>` | Tag number |
323/// | [`tag_content`](Self::tag_content) | `Result<&Value>` | Borrowed content |
324/// | [`tag_content_mut`](Self::tag_content_mut) | `Result<&mut Value>` | Mutable content |
325/// | [`as_tag`](Self::as_tag) | `Result<(u64, &Value)>` | Both parts |
326/// | [`as_tag_mut`](Self::as_tag_mut) | `Result<(u64, &mut Value)>` | Mutable content |
327/// | [`into_tag`](Self::into_tag) | `Result<(u64, Value)>` | Consuming |
328///
329/// Use [`untagged`](Self::untagged) to look through tags without removing
330/// them, [`remove_tag`](Self::remove_tag) to strip the outermost tag, or
331/// [`remove_all_tags`](Self::remove_all_tags) to strip all layers at once.
332///
333/// ```
334/// use cbor_core::Value;
335///
336/// // Create a tagged value (tag 32 = URI)
337/// let mut uri = Value::tag(32, "https://example.com");
338///
339/// // Inspect
340/// let (tag_num, content) = uri.as_tag().unwrap();
341/// assert_eq!(tag_num, 32);
342/// assert_eq!(content.as_str().unwrap(), "https://example.com");
343///
344/// // Look through tags without removing them
345/// assert_eq!(uri.untagged().as_str().unwrap(), "https://example.com");
346///
347/// // Strip the tag in place
348/// let removed = uri.remove_tag();
349/// assert_eq!(removed, Some(32));
350/// assert_eq!(uri.as_str().unwrap(), "https://example.com");
351/// ```
352///
353/// Accessor methods see through tags transparently: calling `as_str()`
354/// on a tagged text string works without manually unwrapping the tag
355/// first. This applies to all accessors (`to_*`, `as_*`, `into_*`).
356///
357/// ```
358/// use cbor_core::Value;
359///
360/// let uri = Value::tag(32, "https://example.com");
361/// assert_eq!(uri.as_str().unwrap(), "https://example.com");
362///
363/// // Nested tags are also transparent
364/// let nested = Value::tag(100, Value::tag(200, 42));
365/// assert_eq!(nested.to_u32().unwrap(), 42);
366/// ```
367///
368/// Big integers are internally represented as tagged byte strings
369/// (tags 2 and 3). The integer accessors recognise these tags and
370/// decode the bytes automatically, even when wrapped in additional
371/// custom tags. Byte-level accessors like `as_bytes()` also see
372/// through tags, so calling `as_bytes()` on a big integer returns
373/// the raw payload bytes.
374///
375/// If a tag is removed via `remove_tag`, `remove_all_tags`, or by
376/// consuming through `into_tag`, the value becomes a plain byte
377/// string and can no longer be read as an integer.
378///
379/// # Type introspection
380///
381/// [`data_type`](Self::data_type) returns a [`DataType`] enum for
382/// lightweight type checks without matching on the full enum.
383///
384/// ```
385/// use cbor_core::Value;
386///
387/// let v = Value::from(3.14);
388/// assert!(v.data_type().is_float());
389/// ```
390#[derive(Clone)]
391pub enum Value {
392    /// Simple value such as `null`, `true`, or `false` (major type 7).
393    ///
394    /// In CBOR, booleans and null are simple values, not distinct types.
395    /// A `Value::from(true)` is stored as `SimpleValue(21)` and is
396    /// accessible through both [`to_bool`](Self::to_bool) and
397    /// [`to_simple_value`](Self::to_simple_value).
398    SimpleValue(SimpleValue),
399
400    /// Unsigned integer (major type 0). Stores values 0 through 2^64-1.
401    Unsigned(u64),
402
403    /// Negative integer (major type 1). The actual value is -1 - n,
404    /// covering -1 through -2^64.
405    Negative(u64),
406
407    /// IEEE 754 floating-point number (major type 7, additional info 25-27).
408    Float(Float),
409
410    /// Byte string (major type 2).
411    ByteString(Vec<u8>),
412
413    /// UTF-8 text string (major type 3).
414    TextString(String),
415
416    /// Array of data items (major type 4).
417    Array(Vec<Value>),
418
419    /// Map of key-value pairs in canonical order (major type 5).
420    Map(BTreeMap<Value, Value>),
421
422    /// Tagged data item (major type 6). The first field is the tag number,
423    /// the second is the enclosed content.
424    Tag(u64, Box<Value>),
425}
426
427// --- CBOR::Core diagnostic notation (Section 2.3.6) ---
428//
429// `Debug` outputs diagnostic notation. The `#` (alternate/pretty) flag
430// enables multi-line output for arrays and maps with indentation.
431impl fmt::Debug for Value {
432    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
433        match self {
434            Self::SimpleValue(sv) => match *sv {
435                SimpleValue::FALSE => f.write_str("false"),
436                SimpleValue::TRUE => f.write_str("true"),
437                SimpleValue::NULL => f.write_str("null"),
438                other => write!(f, "simple({})", other.0),
439            },
440
441            Self::Unsigned(n) => write!(f, "{n}"),
442
443            Self::Negative(n) => write!(f, "{actual}", actual = -i128::from(*n) - 1),
444
445            Self::Float(float) => {
446                let value = float.to_f64();
447                if value.is_nan() {
448                    use crate::float::Inner;
449                    match float.0 {
450                        Inner::F16(0x7e00) => f.write_str("NaN"), // Default NaN is the canonical f16 quiet NaN (f97e00)
451                        Inner::F16(bits) => write!(f, "float'{bits:04x}'"),
452                        Inner::F32(bits) => write!(f, "float'{bits:08x}'"),
453                        Inner::F64(bits) => write!(f, "float'{bits:016x}'"),
454                    }
455                } else if value.is_infinite() {
456                    if value.is_sign_positive() {
457                        f.write_str("Infinity")
458                    } else {
459                        f.write_str("-Infinity")
460                    }
461                } else {
462                    let s = format!("{value}");
463                    f.write_str(&s)?;
464                    if !s.contains('.') && !s.contains('e') && !s.contains('E') {
465                        f.write_str(".0")?; // ensure a decimal point is present
466                    }
467                    Ok(())
468                }
469            }
470
471            Self::ByteString(bytes) => {
472                f.write_str("h'")?;
473                for b in bytes {
474                    write!(f, "{b:02x}")?;
475                }
476                f.write_str("'")
477            }
478
479            Self::TextString(s) => {
480                f.write_str("\"")?;
481                for c in s.chars() {
482                    match c {
483                        '"' => f.write_str("\\\"")?,
484                        '\\' => f.write_str("\\\\")?,
485                        '\u{08}' => f.write_str("\\b")?,
486                        '\u{0C}' => f.write_str("\\f")?,
487                        '\n' => f.write_str("\\n")?,
488                        '\r' => f.write_str("\\r")?,
489                        '\t' => f.write_str("\\t")?,
490                        c if c.is_control() => write!(f, "\\u{:04x}", c as u32)?,
491                        c => write!(f, "{c}")?,
492                    }
493                }
494                f.write_str("\"")
495            }
496
497            Self::Array(items) => {
498                let mut list = f.debug_list();
499                for item in items {
500                    list.entry(item);
501                }
502                list.finish()
503            }
504
505            Self::Map(map) => {
506                let mut m = f.debug_map();
507                for (key, value) in map {
508                    m.entry(key, value);
509                }
510                m.finish()
511            }
512
513            Self::Tag(tag, content) => {
514                // Big integers: show as decimal when they fit in i128/u128
515                if self.data_type().is_integer() {
516                    if let Ok(n) = self.to_u128() {
517                        return write!(f, "{n}");
518                    }
519                    if let Ok(n) = self.to_i128() {
520                        return write!(f, "{n}");
521                    }
522                }
523
524                if f.alternate() {
525                    write!(f, "{tag}({content:#?})")
526                } else {
527                    write!(f, "{tag}({content:?})")
528                }
529            }
530        }
531    }
532}
533
534impl Value {
535    /// Take the value out, leaving `null` in its place.
536    ///
537    /// ```
538    /// use cbor_core::Value;
539    ///
540    /// let mut v = Value::from(42);
541    /// let taken = v.take();
542    /// assert_eq!(taken.to_u32().unwrap(), 42);
543    /// assert!(v.data_type().is_null());
544    /// ```
545    pub fn take(&mut self) -> Self {
546        std::mem::take(self)
547    }
548
549    /// Replace the value, returning the old one.
550    ///
551    /// ```
552    /// use cbor_core::Value;
553    ///
554    /// let mut v = Value::from("hello");
555    /// let old = v.replace(Value::from("world"));
556    /// assert_eq!(old.as_str().unwrap(), "hello");
557    /// assert_eq!(v.as_str().unwrap(), "world");
558    /// ```
559    pub fn replace(&mut self, value: Self) -> Self {
560        std::mem::replace(self, value)
561    }
562
563    /// Encode this value to binary CBOR bytes.
564    ///
565    /// This is a convenience wrapper around [`write_to`](Self::write_to).
566    ///
567    /// ```
568    /// use cbor_core::Value;
569    /// let bytes = Value::from(42).encode();
570    /// assert_eq!(bytes, [0x18, 42]);
571    /// ```
572    #[must_use]
573    pub fn encode(&self) -> Vec<u8> {
574        let len = self.cbor_len();
575        let mut bytes = Vec::with_capacity(len);
576        self.write_to(&mut bytes).unwrap();
577        debug_assert_eq!(bytes.len(), len);
578        bytes
579    }
580
581    /// Encode this value to a hex-encoded CBOR string.
582    ///
583    /// This is a convenience wrapper around [`write_hex_to`](Self::write_hex_to).
584    ///
585    /// ```
586    /// use cbor_core::Value;
587    /// let hex = Value::from(42).encode_hex();
588    /// assert_eq!(hex, "182a");
589    /// ```
590    #[must_use]
591    pub fn encode_hex(&self) -> String {
592        let len2 = self.cbor_len() * 2;
593        let mut hex = Vec::with_capacity(len2);
594        self.write_hex_to(&mut hex).unwrap();
595        debug_assert_eq!(hex.len(), len2);
596        String::from_utf8(hex).unwrap()
597    }
598
599    /// Decode a CBOR data item from binary bytes.
600    ///
601    /// Accepts any byte source (`&[u8]`, `&str`, `String`, `Vec<u8>`, etc.).
602    /// Returns `Err` if the encoding is not canonical.
603    ///
604    /// This is a convenience wrapper around [`read_from`](Self::read_from).
605    ///
606    /// ```
607    /// use cbor_core::Value;
608    /// let v = Value::decode([0x18, 42]).unwrap();
609    /// assert_eq!(v.to_u32().unwrap(), 42);
610    /// ```
611    pub fn decode(bytes: impl AsRef<[u8]>) -> crate::Result<Self> {
612        let mut bytes = bytes.as_ref();
613        Self::read_from(&mut bytes).map_err(|error| match error {
614            crate::IoError::Io(_io_error) => unreachable!(),
615            crate::IoError::Data(error) => error,
616        })
617    }
618
619    /// Decode a CBOR data item from hex-encoded bytes.
620    ///
621    /// Accepts any byte source (`&[u8]`, `&str`, `String`, `Vec<u8>`, etc.).
622    /// Both uppercase and lowercase hex digits are accepted.
623    /// Returns `Err` if the encoding is not canonical.
624    ///
625    /// This is a convenience wrapper around [`read_hex_from`](Self::read_hex_from).
626    ///
627    /// ```
628    /// use cbor_core::Value;
629    /// let v = Value::decode_hex("182a").unwrap();
630    /// assert_eq!(v.to_u32().unwrap(), 42);
631    /// ```
632    pub fn decode_hex(hex: impl AsRef<[u8]>) -> Result<Self> {
633        let mut bytes = hex.as_ref();
634        Self::read_hex_from(&mut bytes).map_err(|error| match error {
635            crate::IoError::Io(_io_error) => unreachable!(),
636            crate::IoError::Data(error) => error,
637        })
638    }
639
640    /// Read a single CBOR data item from a binary stream.
641    ///
642    /// ```
643    /// use cbor_core::Value;
644    /// let mut bytes: &[u8] = &[0x18, 42];
645    /// let v = Value::read_from(&mut bytes).unwrap();
646    /// assert_eq!(v.to_u32().unwrap(), 42);
647    /// ```
648    pub fn read_from(mut reader: impl io::Read) -> crate::IoResult<Self> {
649        Self::read_from_inner(&mut reader, RECURSION_LIMIT, OOM_MITIGATION)
650    }
651
652    fn read_from_inner(
653        reader: &mut impl io::Read,
654        recursion_limit: u16,
655        oom_mitigation: usize,
656    ) -> crate::IoResult<Self> {
657        let ctrl_byte = {
658            let mut buf = [0];
659            reader.read_exact(&mut buf)?;
660            buf[0]
661        };
662
663        let is_float = matches!(ctrl_byte, CtrlByte::F16 | CtrlByte::F32 | CtrlByte::F64);
664
665        let major = ctrl_byte >> 5;
666        let info = ctrl_byte & 0x1f;
667
668        let argument = {
669            let mut buf = [0; 8];
670
671            if info < ArgLength::U8 {
672                buf[7] = info;
673            } else {
674                match info {
675                    ArgLength::U8 => reader.read_exact(&mut buf[7..])?,
676                    ArgLength::U16 => reader.read_exact(&mut buf[6..])?,
677                    ArgLength::U32 => reader.read_exact(&mut buf[4..])?,
678                    ArgLength::U64 => reader.read_exact(&mut buf)?,
679                    _ => return Error::Malformed.into(),
680                }
681            }
682
683            u64::from_be_bytes(buf)
684        };
685
686        if !is_float {
687            let non_deterministic = match info {
688                ArgLength::U8 => argument < u64::from(ArgLength::U8),
689                ArgLength::U16 => argument <= u64::from(u8::MAX),
690                ArgLength::U32 => argument <= u64::from(u16::MAX),
691                ArgLength::U64 => argument <= u64::from(u32::MAX),
692                _ => false,
693            };
694
695            if non_deterministic {
696                return Error::NonDeterministic.into();
697            }
698        }
699
700        let this = match major {
701            Major::UNSIGNED => Self::Unsigned(argument),
702            Major::NEGATIVE => Self::Negative(argument),
703
704            Major::BYTE_STRING => Self::ByteString(read_vec(reader, argument)?),
705
706            Major::TEXT_STRING => {
707                let bytes = read_vec(reader, argument)?;
708                let string = String::from_utf8(bytes)?;
709                Self::TextString(string)
710            }
711
712            Major::ARRAY => {
713                if argument > LENGTH_LIMIT {
714                    return Error::LengthTooLarge.into();
715                }
716
717                let Some(recursion_limit) = recursion_limit.checked_sub(1) else {
718                    return Error::LengthTooLarge.into();
719                };
720
721                let request: usize = argument.try_into().or(Err(Error::LengthTooLarge))?;
722                let granted = request.min(oom_mitigation / size_of::<Self>());
723                let oom_mitigation = oom_mitigation - granted * size_of::<Self>();
724
725                let mut vec = Vec::with_capacity(granted);
726
727                for _ in 0..argument {
728                    vec.push(Self::read_from_inner(reader, recursion_limit, oom_mitigation)?);
729                }
730
731                Self::Array(vec)
732            }
733
734            Major::MAP => {
735                if argument > LENGTH_LIMIT {
736                    return Error::LengthTooLarge.into();
737                }
738
739                let Some(recursion_limit) = recursion_limit.checked_sub(1) else {
740                    return Error::LengthTooLarge.into();
741                };
742
743                let mut map = BTreeMap::new();
744                let mut prev = None;
745
746                for _ in 0..argument {
747                    let key = Self::read_from_inner(reader, recursion_limit, oom_mitigation)?;
748                    let value = Self::read_from_inner(reader, recursion_limit, oom_mitigation)?;
749
750                    if let Some((prev_key, prev_value)) = prev.take() {
751                        if prev_key >= key {
752                            return Error::NonDeterministic.into();
753                        }
754                        map.insert(prev_key, prev_value);
755                    }
756
757                    prev = Some((key, value));
758                }
759
760                if let Some((key, value)) = prev.take() {
761                    map.insert(key, value);
762                }
763
764                Self::Map(map)
765            }
766
767            Major::TAG => {
768                let Some(recursion_limit) = recursion_limit.checked_sub(1) else {
769                    return Error::LengthTooLarge.into();
770                };
771
772                let content = Box::new(Self::read_from_inner(reader, recursion_limit, oom_mitigation)?);
773
774                // check if conforming bigint
775                if matches!(argument, Tag::POS_BIG_INT | Tag::NEG_BIG_INT)
776                    && let Ok(bigint) = content.as_bytes()
777                {
778                    let valid = bigint.len() >= 8 && bigint[0] != 0;
779                    if !valid {
780                        return Error::NonDeterministic.into();
781                    }
782                }
783
784                Self::Tag(argument, content)
785            }
786
787            Major::SIMPLE_VALUE => match info {
788                0..ArgLength::U8 => Self::SimpleValue(SimpleValue(argument as u8)),
789                ArgLength::U8 if argument >= 32 => Self::SimpleValue(SimpleValue(argument as u8)),
790
791                ArgLength::U16 => Self::Float(Float::from_u16(argument as u16)),
792                ArgLength::U32 => Self::Float(Float::from_u32(argument as u32)?),
793                ArgLength::U64 => Self::Float(Float::from_u64(argument)?),
794
795                _ => return Error::Malformed.into(),
796            },
797
798            _ => unreachable!(),
799        };
800
801        Ok(this)
802    }
803
804    /// Read a single CBOR data item from a hex-encoded stream.
805    ///
806    /// Each byte of CBOR is expected as two hex digits (uppercase or
807    /// lowercase).
808    ///
809    /// ```
810    /// use cbor_core::Value;
811    /// let mut hex = "182a".as_bytes();
812    /// let v = Value::read_hex_from(&mut hex).unwrap();
813    /// assert_eq!(v.to_u32().unwrap(), 42);
814    /// ```
815    pub fn read_hex_from(reader: impl io::Read) -> crate::IoResult<Self> {
816        struct HexReader<R>(R, Option<Error>);
817
818        impl<R: io::Read> io::Read for HexReader<R> {
819            fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
820                fn nibble(char: u8) -> Option<u8> {
821                    match char {
822                        b'0'..=b'9' => Some(char - b'0'),
823                        b'a'..=b'f' => Some(char - b'a' + 10),
824                        b'A'..=b'F' => Some(char - b'A' + 10),
825                        _ => None,
826                    }
827                }
828
829                for byte in buf.iter_mut() {
830                    let mut hex = [0; 2];
831                    self.0.read_exact(&mut hex)?;
832
833                    if let Some(n0) = nibble(hex[0])
834                        && let Some(n1) = nibble(hex[1])
835                    {
836                        *byte = n0 << 4 | n1
837                    } else {
838                        self.1 = Some(Error::InvalidHex);
839                        return Err(io::Error::other("invalid hex character"));
840                    }
841                }
842
843                Ok(buf.len())
844            }
845        }
846
847        let mut hex_reader = HexReader(reader, None);
848        let result = Self::read_from_inner(&mut hex_reader, RECURSION_LIMIT, OOM_MITIGATION);
849
850        if let Some(error) = hex_reader.1 {
851            error.into()
852        } else {
853            result
854        }
855    }
856
857    /// Write this value as binary CBOR to a stream.
858    ///
859    /// ```
860    /// use cbor_core::Value;
861    /// let mut buf = Vec::new();
862    /// Value::from(42).write_to(&mut buf).unwrap();
863    /// assert_eq!(buf, [0x18, 42]);
864    /// ```
865    pub fn write_to(&self, mut writer: impl io::Write) -> crate::IoResult<()> {
866        self.write_to_inner(&mut writer)
867    }
868
869    fn write_to_inner(&self, writer: &mut impl io::Write) -> crate::IoResult<()> {
870        let major = self.cbor_major();
871        let (info, argument) = self.cbor_argument();
872
873        let ctrl_byte = major << 5 | info;
874        writer.write_all(&[ctrl_byte])?;
875
876        let buf = argument.to_be_bytes();
877        match info {
878            ArgLength::U8 => writer.write_all(&buf[7..])?,
879            ArgLength::U16 => writer.write_all(&buf[6..])?,
880            ArgLength::U32 => writer.write_all(&buf[4..])?,
881            ArgLength::U64 => writer.write_all(&buf)?,
882            _ => (), // argument embedded in ctrl byte
883        }
884
885        match self {
886            Value::ByteString(bytes) => writer.write_all(bytes)?,
887            Value::TextString(string) => writer.write_all(string.as_bytes())?,
888
889            Value::Tag(_number, content) => content.write_to_inner(writer)?,
890
891            Value::Array(values) => {
892                for value in values {
893                    value.write_to_inner(writer)?;
894                }
895            }
896
897            Value::Map(map) => {
898                for (key, value) in map {
899                    key.write_to_inner(writer)?;
900                    value.write_to_inner(writer)?;
901                }
902            }
903
904            _ => (),
905        }
906
907        Ok(())
908    }
909
910    /// Write this value as hex-encoded CBOR to a stream.
911    ///
912    /// Each binary byte is written as two lowercase hex digits. The
913    /// adapter encodes on the fly without buffering the full output.
914    ///
915    /// ```
916    /// use cbor_core::Value;
917    /// let mut buf = Vec::new();
918    /// Value::from(42).write_hex_to(&mut buf).unwrap();
919    /// assert_eq!(buf, b"182a");
920    /// ```
921    pub fn write_hex_to(&self, writer: impl io::Write) -> crate::IoResult<()> {
922        struct HexWriter<W>(W);
923
924        impl<W: io::Write> io::Write for HexWriter<W> {
925            fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
926                for &byte in buf {
927                    write!(self.0, "{byte:02x}")?;
928                }
929                Ok(buf.len())
930            }
931            fn flush(&mut self) -> io::Result<()> {
932                Ok(())
933            }
934        }
935
936        self.write_to_inner(&mut HexWriter(writer))
937    }
938
939    fn cbor_major(&self) -> u8 {
940        match self {
941            Value::Unsigned(_) => Major::UNSIGNED,
942            Value::Negative(_) => Major::NEGATIVE,
943            Value::ByteString(_) => Major::BYTE_STRING,
944            Value::TextString(_) => Major::TEXT_STRING,
945            Value::Array(_) => Major::ARRAY,
946            Value::Map(_) => Major::MAP,
947            Value::Tag(_, _) => Major::TAG,
948            Value::SimpleValue(_) => Major::SIMPLE_VALUE,
949            Value::Float(_) => Major::SIMPLE_VALUE,
950        }
951    }
952
953    fn cbor_argument(&self) -> (u8, u64) {
954        fn arg(value: u64) -> (u8, u64) {
955            if value < u64::from(ArgLength::U8) {
956                (value as u8, value)
957            } else {
958                let info = match value {
959                    0x00..=0xFF => ArgLength::U8,
960                    0x100..=0xFFFF => ArgLength::U16,
961                    0x10000..=0xFFFF_FFFF => ArgLength::U32,
962                    _ => ArgLength::U64,
963                };
964                (info, value)
965            }
966        }
967
968        match self {
969            Value::Unsigned(value) => arg(*value),
970            Value::Negative(value) => arg(*value),
971            Value::ByteString(vec) => arg(vec.len().try_into().unwrap()),
972            Value::TextString(str) => arg(str.len().try_into().unwrap()),
973            Value::Array(vec) => arg(vec.len().try_into().unwrap()),
974            Value::Map(map) => arg(map.len().try_into().unwrap()),
975            Value::Tag(number, _) => arg(*number),
976            Value::SimpleValue(value) => arg(value.0.into()),
977            Value::Float(float) => float.cbor_argument(),
978        }
979    }
980
981    /// Encoded length
982    fn cbor_len(&self) -> usize {
983        let (info, _) = self.cbor_argument();
984
985        let header_len = match info {
986            0..ArgLength::U8 => 1,
987            ArgLength::U8 => 2,
988            ArgLength::U16 => 3,
989            ArgLength::U32 => 5,
990            ArgLength::U64 => 9,
991            _ => unreachable!(),
992        };
993
994        let data_len = match self {
995            Self::ByteString(bytes) => bytes.len(),
996            Self::TextString(text) => text.len(),
997            Self::Array(vec) => vec.iter().map(Self::cbor_len).sum(),
998            Self::Map(map) => map.iter().map(|(k, v)| k.cbor_len() + v.cbor_len()).sum(),
999            Self::Tag(_, content) => content.cbor_len(),
1000            _ => 0,
1001        };
1002
1003        header_len + data_len
1004    }
1005
1006    // ------------------- constructors -------------------
1007
1008    /// Create a CBOR null value.
1009    #[must_use]
1010    pub const fn null() -> Self {
1011        Self::SimpleValue(SimpleValue::NULL)
1012    }
1013
1014    /// Create a CBOR simple value.
1015    ///
1016    /// # Panics
1017    ///
1018    /// Panics if the value is in the reserved range 24-31.
1019    /// Use [`SimpleValue::from_u8`] for a fallible alternative.
1020    pub fn simple_value(value: impl TryInto<SimpleValue>) -> Self {
1021        match value.try_into() {
1022            Ok(sv) => Self::SimpleValue(sv),
1023            Err(_) => panic!("Invalid simple value"),
1024        }
1025    }
1026
1027    /// Create a CBOR date/time string value (tag 0).
1028    ///
1029    /// Accepts `&str`, `String`, and [`SystemTime`] via the
1030    /// [`DateTime`] helper. The date must be within
1031    /// `0001-01-01T00:00:00Z` to `9999-12-31T23:59:59Z`.
1032    ///
1033    /// # Panics
1034    ///
1035    /// Panics if the input is not a valid RFC 3339 (ISO 8601 profile)
1036    /// UTC timestamp or is out of range.
1037    ///
1038    /// ```
1039    /// use cbor_core::{DataType, Value};
1040    ///
1041    /// let v = Value::date_time("2000-01-01T00:00:00.000Z");
1042    /// assert_eq!(v.data_type(), DataType::DateTime);
1043    /// assert_eq!(v.as_str(), Ok("2000-01-01T00:00:00.000Z"));
1044    ///
1045    /// use std::time::SystemTime;
1046    /// let v = Value::date_time(SystemTime::UNIX_EPOCH);
1047    /// assert_eq!(v.data_type(), DataType::DateTime);
1048    /// assert_eq!(v.as_str(), Ok("1970-01-01T00:00:00Z"));
1049    /// ```
1050    pub fn date_time(value: impl TryInto<DateTime>) -> Self {
1051        match value.try_into() {
1052            Ok(dt) => dt.into(),
1053            Err(_) => panic!("Invalid date/time"),
1054        }
1055    }
1056
1057    /// Create a CBOR epoch time value (tag 1).
1058    ///
1059    /// Accepts integers, floats, and [`SystemTime`] via the
1060    /// [`EpochTime`] helper. The value must be in the range 0 to
1061    /// 253402300799.
1062    ///
1063    /// # Panics
1064    ///
1065    /// Panics if the value is out of range or negative.
1066    ///
1067    /// ```
1068    /// use std::time::{Duration, UNIX_EPOCH};
1069    /// use cbor_core::Value;
1070    ///
1071    /// let v = Value::epoch_time(1_000_000);
1072    /// assert_eq!(v.to_system_time(), Ok(UNIX_EPOCH + Duration::from_secs(1_000_000)));
1073    /// ```
1074    pub fn epoch_time(value: impl TryInto<EpochTime>) -> Self {
1075        match value.try_into() {
1076            Ok(et) => et.into(),
1077            Err(_) => panic!("Invalid epoch time"),
1078        }
1079    }
1080
1081    /// Create a CBOR float.
1082    ///
1083    /// Via the [`Float`] type floats can be created out of integers and booleans too.
1084    ///
1085    /// ```
1086    /// use cbor_core::Value;
1087    ///
1088    /// let f1 = Value::float(1.0);
1089    /// assert!(f1.to_f64() == Ok(1.0));
1090    ///
1091    /// let f2 = Value::float(2);
1092    /// assert!(f2.to_f64() == Ok(2.0));
1093    ///
1094    /// let f3 = Value::float(true);
1095    /// assert!(f3.to_f64() == Ok(1.0));
1096    /// ```
1097    ///
1098    /// The value is stored in the shortest IEEE 754 form (f16, f32,
1099    /// or f64) that preserves it exactly.
1100    pub fn float(value: impl Into<Float>) -> Self {
1101        Self::Float(value.into())
1102    }
1103
1104    /// Create a CBOR array.
1105    ///
1106    /// Accepts any type that converts into [`Array`], including
1107    /// `Vec<T>`, `[T; N]`, `&[T]`, and `Box<[T]>` where `T: Into<Value>`.
1108    /// See [`Array`] for the full list of accepted types.
1109    ///
1110    /// ```
1111    /// # use cbor_core::Value;
1112    /// let a = Value::array([1, 2, 3]);
1113    /// assert_eq!(a.as_array().unwrap().len(), 3);
1114    /// ```
1115    pub fn array(array: impl Into<Array>) -> Self {
1116        Self::Array(array.into().0)
1117    }
1118
1119    /// Create a CBOR map. Keys are stored in canonical order.
1120    ///
1121    /// Accepts any type that converts into [`Map`], including
1122    /// `BTreeMap`, `&HashMap`, `Vec<(K, V)>`, `[(K, V); N]`, and
1123    /// `&[(K, V)]`. See [`Map`] for the full list of accepted types.
1124    ///
1125    /// ```
1126    /// # use cbor_core::Value;
1127    /// let m = Value::map([("x", 1), ("y", 2)]);
1128    /// assert_eq!(m.as_map().unwrap().len(), 2);
1129    /// ```
1130    pub fn map(map: impl Into<Map>) -> Self {
1131        Self::Map(map.into().0)
1132    }
1133
1134    /// Wrap a value with a CBOR tag.
1135    ///
1136    /// ```
1137    /// use cbor_core::Value;
1138    /// let uri = Value::tag(32, "https://example.com");
1139    /// assert_eq!(uri.tag_number().unwrap(), 32);
1140    /// ```
1141    pub fn tag(number: u64, content: impl Into<Value>) -> Self {
1142        Self::Tag(number, Box::new(content.into()))
1143    }
1144
1145    /// Return the [`DataType`] of this value for type-level dispatch.
1146    #[must_use]
1147    pub const fn data_type(&self) -> DataType {
1148        match self {
1149            Self::SimpleValue(sv) => sv.data_type(),
1150
1151            Self::Unsigned(_) | Self::Negative(_) => DataType::Int,
1152
1153            Self::Float(float) => float.data_type(),
1154
1155            Self::TextString(_) => DataType::Text,
1156            Self::ByteString(_) => DataType::Bytes,
1157
1158            Self::Array(_) => DataType::Array,
1159            Self::Map(_) => DataType::Map,
1160
1161            Self::Tag(Tag::DATE_TIME, content) if content.data_type().is_text() => DataType::DateTime,
1162            Self::Tag(Tag::EPOCH_TIME, content) if content.data_type().is_numeric() => DataType::EpochTime,
1163
1164            Self::Tag(Tag::POS_BIG_INT | Tag::NEG_BIG_INT, content) if content.data_type().is_bytes() => {
1165                DataType::BigInt
1166            }
1167
1168            Self::Tag(_, _) => DataType::Tag,
1169        }
1170    }
1171
1172    /// Internal shortcut helper
1173    pub(crate) const fn is_bytes(&self) -> bool {
1174        self.data_type().is_bytes()
1175    }
1176
1177    /// Extract a boolean. Returns `Err` for non-boolean values.
1178    pub const fn to_bool(&self) -> Result<bool> {
1179        match self {
1180            Self::SimpleValue(sv) => sv.to_bool(),
1181            Self::Tag(_number, content) => content.untagged().to_bool(),
1182            _ => Err(Error::IncompatibleType(self.data_type())),
1183        }
1184    }
1185
1186    /// Extract the raw simple value number (0-255, excluding 24-31).
1187    pub const fn to_simple_value(&self) -> Result<u8> {
1188        match self {
1189            Self::SimpleValue(sv) => Ok(sv.0),
1190            Self::Tag(_number, content) => content.untagged().to_simple_value(),
1191            _ => Err(Error::IncompatibleType(self.data_type())),
1192        }
1193    }
1194
1195    fn to_uint<T>(&self) -> Result<T>
1196    where
1197        T: TryFrom<u64> + TryFrom<u128>,
1198    {
1199        match self {
1200            Self::Unsigned(x) => T::try_from(*x).or(Err(Error::Overflow)),
1201            Self::Negative(_) => Err(Error::NegativeUnsigned),
1202
1203            Self::Tag(Tag::POS_BIG_INT, content) if content.is_bytes() => {
1204                T::try_from(u128_from_slice(self.as_bytes()?)?).or(Err(Error::Overflow))
1205            }
1206
1207            Self::Tag(Tag::NEG_BIG_INT, content) if content.is_bytes() => Err(Error::NegativeUnsigned),
1208            Self::Tag(_other_number, content) => content.peeled().to_uint(),
1209            _ => Err(Error::IncompatibleType(self.data_type())),
1210        }
1211    }
1212
1213    /// Narrow to `u8`. Returns `Err(Overflow)` or `Err(NegativeUnsigned)` on mismatch.
1214    pub fn to_u8(&self) -> Result<u8> {
1215        self.to_uint()
1216    }
1217
1218    /// Narrow to `u16`.
1219    pub fn to_u16(&self) -> Result<u16> {
1220        self.to_uint()
1221    }
1222
1223    /// Narrow to `u32`.
1224    pub fn to_u32(&self) -> Result<u32> {
1225        self.to_uint()
1226    }
1227
1228    /// Narrow to `u64`.
1229    pub fn to_u64(&self) -> Result<u64> {
1230        self.to_uint()
1231    }
1232
1233    /// Narrow to `u128`. Handles big integers (tag 2) transparently.
1234    pub fn to_u128(&self) -> Result<u128> {
1235        self.to_uint()
1236    }
1237
1238    /// Narrow to `usize`.
1239    pub fn to_usize(&self) -> Result<usize> {
1240        self.to_uint()
1241    }
1242
1243    #[allow(dead_code)]
1244    pub(crate) fn as_integer_bytes(&self) -> Result<IntegerBytes<'_>> {
1245        match self {
1246            Self::Unsigned(x) => Ok(IntegerBytes::UnsignedOwned(x.to_be_bytes())),
1247            Self::Negative(x) => Ok(IntegerBytes::NegativeOwned(x.to_be_bytes())),
1248
1249            Self::Tag(Tag::POS_BIG_INT, content) if content.is_bytes() => {
1250                Ok(IntegerBytes::UnsignedBorrowed(content.as_bytes()?))
1251            }
1252
1253            Self::Tag(Tag::NEG_BIG_INT, content) if content.is_bytes() => {
1254                Ok(IntegerBytes::NegativeBorrowed(content.as_bytes()?))
1255            }
1256
1257            Self::Tag(_other_number, content) => content.peeled().as_integer_bytes(),
1258            _ => Err(Error::IncompatibleType(self.data_type())),
1259        }
1260    }
1261
1262    fn to_sint<T>(&self) -> Result<T>
1263    where
1264        T: TryFrom<u64> + TryFrom<u128> + std::ops::Not<Output = T>,
1265    {
1266        match self {
1267            Self::Unsigned(x) => T::try_from(*x).or(Err(Error::Overflow)),
1268            Self::Negative(x) => T::try_from(*x).map(T::not).or(Err(Error::Overflow)),
1269
1270            Self::Tag(Tag::POS_BIG_INT, content) if content.is_bytes() => {
1271                T::try_from(u128_from_slice(self.as_bytes()?)?).or(Err(Error::Overflow))
1272            }
1273
1274            Self::Tag(Tag::NEG_BIG_INT, content) if content.is_bytes() => {
1275                T::try_from(u128_from_slice(self.as_bytes()?)?)
1276                    .map(T::not)
1277                    .or(Err(Error::Overflow))
1278            }
1279
1280            Self::Tag(_other_number, content) => content.peeled().to_sint(),
1281            _ => Err(Error::IncompatibleType(self.data_type())),
1282        }
1283    }
1284
1285    /// Narrow to `i8`.
1286    pub fn to_i8(&self) -> Result<i8> {
1287        self.to_sint()
1288    }
1289
1290    /// Narrow to `i16`.
1291    pub fn to_i16(&self) -> Result<i16> {
1292        self.to_sint()
1293    }
1294
1295    /// Narrow to `i32`.
1296    pub fn to_i32(&self) -> Result<i32> {
1297        self.to_sint()
1298    }
1299
1300    /// Narrow to `i64`.
1301    pub fn to_i64(&self) -> Result<i64> {
1302        self.to_sint()
1303    }
1304
1305    /// Narrow to `i128`. Handles big integers (tags 2 and 3) transparently.
1306    pub fn to_i128(&self) -> Result<i128> {
1307        self.to_sint()
1308    }
1309
1310    /// Narrow to `isize`.
1311    pub fn to_isize(&self) -> Result<isize> {
1312        self.to_sint()
1313    }
1314
1315    /// Convert to `f32`.
1316    ///
1317    /// Returns `Err(Precision)` for f64-width values.
1318    pub fn to_f32(&self) -> Result<f32> {
1319        match self {
1320            Self::Float(float) => float.to_f32(),
1321            Self::Tag(_number, content) => content.untagged().to_f32(),
1322            _ => Err(Error::IncompatibleType(self.data_type())),
1323        }
1324    }
1325
1326    /// Convert to `f64`.
1327    ///
1328    /// Always succeeds for float values.
1329    pub fn to_f64(&self) -> Result<f64> {
1330        match self {
1331            Self::Float(float) => Ok(float.to_f64()),
1332            Self::Tag(_number, content) => content.untagged().to_f64(),
1333            _ => Err(Error::IncompatibleType(self.data_type())),
1334        }
1335    }
1336
1337    /// Convert a time value to [`SystemTime`].
1338    ///
1339    /// Accepts date/time strings (tag 0), epoch time values (tag 1),
1340    /// and untagged integers or floats. Numeric values must be
1341    /// non-negative and in the range 0 to 253402300799. Date/time
1342    /// strings may include a timezone offset, which is converted to
1343    /// UTC.
1344    ///
1345    /// Returns `Err(IncompatibleType)` for values that are neither
1346    /// numeric nor text, `Err(InvalidValue)` if a numeric value is out of
1347    /// range, and `Err(InvalidFormat)` if a text string is not a
1348    /// valid RFC 3339 timestamp. Leap seconds (`:60`) are rejected
1349    /// because [`SystemTime`] cannot represent them.
1350    ///
1351    /// ```
1352    /// use std::time::{Duration, UNIX_EPOCH};
1353    /// use cbor_core::Value;
1354    ///
1355    /// let v = Value::tag(1, 1_000_000);
1356    /// let t = v.to_system_time().unwrap();
1357    /// assert_eq!(t, UNIX_EPOCH + Duration::from_secs(1_000_000));
1358    /// ```
1359    pub fn to_system_time(&self) -> Result<SystemTime> {
1360        if let Ok(s) = self.as_str() {
1361            Ok(s.parse::<crate::iso3339::Timestamp>()?.try_into()?)
1362        } else if let Ok(f) = self.to_f64() {
1363            if f.is_finite() && (0.0..=253402300799.0).contains(&f) {
1364                Ok(SystemTime::UNIX_EPOCH + Duration::from_secs_f64(f))
1365            } else {
1366                Err(Error::InvalidValue)
1367            }
1368        } else {
1369            match self.to_u64() {
1370                Ok(secs) if secs <= 253402300799 => Ok(SystemTime::UNIX_EPOCH + Duration::from_secs(secs)),
1371                Ok(_) | Err(Error::NegativeUnsigned) => Err(Error::InvalidValue),
1372                Err(error) => Err(error),
1373            }
1374        }
1375    }
1376
1377    /// Borrow the byte string as a slice.
1378    pub fn as_bytes(&self) -> Result<&[u8]> {
1379        match self {
1380            Self::ByteString(vec) => Ok(vec.as_slice()),
1381            Self::Tag(_number, content) => content.untagged().as_bytes(),
1382            _ => Err(Error::IncompatibleType(self.data_type())),
1383        }
1384    }
1385
1386    /// Borrow the byte string as a mutable `Vec`.
1387    pub const fn as_bytes_mut(&mut self) -> Result<&mut Vec<u8>> {
1388        match self {
1389            Self::ByteString(vec) => Ok(vec),
1390            Self::Tag(_number, content) => content.untagged_mut().as_bytes_mut(),
1391            _ => Err(Error::IncompatibleType(self.data_type())),
1392        }
1393    }
1394
1395    /// Take ownership of the byte string.
1396    pub fn into_bytes(self) -> Result<Vec<u8>> {
1397        match self {
1398            Self::ByteString(vec) => Ok(vec),
1399            Self::Tag(_number, content) => content.into_untagged().into_bytes(),
1400            _ => Err(Error::IncompatibleType(self.data_type())),
1401        }
1402    }
1403
1404    /// Borrow the text string as a `&str`.
1405    pub fn as_str(&self) -> Result<&str> {
1406        match self {
1407            Self::TextString(s) => Ok(s.as_str()),
1408            Self::Tag(_number, content) => content.untagged().as_str(),
1409            _ => Err(Error::IncompatibleType(self.data_type())),
1410        }
1411    }
1412
1413    /// Borrow the text string as a mutable `String`.
1414    pub const fn as_string_mut(&mut self) -> Result<&mut String> {
1415        match self {
1416            Self::TextString(s) => Ok(s),
1417            Self::Tag(_number, content) => content.untagged_mut().as_string_mut(),
1418            _ => Err(Error::IncompatibleType(self.data_type())),
1419        }
1420    }
1421
1422    /// Take ownership of the text string.
1423    pub fn into_string(self) -> Result<String> {
1424        match self {
1425            Self::TextString(s) => Ok(s),
1426            Self::Tag(_number, content) => content.into_untagged().into_string(),
1427            _ => Err(Error::IncompatibleType(self.data_type())),
1428        }
1429    }
1430
1431    /// Borrow the array elements as a slice.
1432    pub fn as_array(&self) -> Result<&[Value]> {
1433        match self {
1434            Self::Array(v) => Ok(v.as_slice()),
1435            Self::Tag(_number, content) => content.untagged().as_array(),
1436            _ => Err(Error::IncompatibleType(self.data_type())),
1437        }
1438    }
1439
1440    /// Borrow the array as a mutable `Vec`.
1441    pub const fn as_array_mut(&mut self) -> Result<&mut Vec<Value>> {
1442        match self {
1443            Self::Array(v) => Ok(v),
1444            Self::Tag(_number, content) => content.untagged_mut().as_array_mut(),
1445            _ => Err(Error::IncompatibleType(self.data_type())),
1446        }
1447    }
1448
1449    /// Take ownership of the array.
1450    pub fn into_array(self) -> Result<Vec<Value>> {
1451        match self {
1452            Self::Array(v) => Ok(v),
1453            Self::Tag(_number, content) => content.into_untagged().into_array(),
1454            _ => Err(Error::IncompatibleType(self.data_type())),
1455        }
1456    }
1457
1458    /// Borrow the map.
1459    pub const fn as_map(&self) -> Result<&BTreeMap<Value, Value>> {
1460        match self {
1461            Self::Map(m) => Ok(m),
1462            Self::Tag(_number, content) => content.untagged().as_map(),
1463            _ => Err(Error::IncompatibleType(self.data_type())),
1464        }
1465    }
1466
1467    /// Borrow the map mutably.
1468    pub const fn as_map_mut(&mut self) -> Result<&mut BTreeMap<Value, Value>> {
1469        match self {
1470            Self::Map(m) => Ok(m),
1471            Self::Tag(_number, content) => content.untagged_mut().as_map_mut(),
1472            _ => Err(Error::IncompatibleType(self.data_type())),
1473        }
1474    }
1475
1476    /// Take ownership of the map.
1477    pub fn into_map(self) -> Result<BTreeMap<Value, Value>> {
1478        match self {
1479            Self::Map(m) => Ok(m),
1480            Self::Tag(_number, content) => content.into_untagged().into_map(),
1481            _ => Err(Error::IncompatibleType(self.data_type())),
1482        }
1483    }
1484
1485    // --------------- Index access ---------------
1486
1487    /// Look up an element by index (arrays) or key (maps).
1488    ///
1489    /// Returns `None` if the value is not an array or map, the index
1490    /// is out of bounds, or the key is missing.
1491    ///
1492    /// ```
1493    /// use cbor_core::{Value, array, map};
1494    ///
1495    /// let a = array![10, 20, 30];
1496    /// assert_eq!(a.get(1).unwrap().to_u32().unwrap(), 20);
1497    /// assert!(a.get(5).is_none());
1498    ///
1499    /// let m = map! { "x" => 10 };
1500    /// assert_eq!(m.get("x").unwrap().to_u32().unwrap(), 10);
1501    /// assert!(m.get("missing").is_none());
1502    /// ```
1503    pub fn get(&self, index: impl Into<Value>) -> Option<&Value> {
1504        let key = index.into();
1505        match self.untagged() {
1506            Value::Array(arr) => key.to_usize().ok().and_then(|i| arr.get(i)),
1507            Value::Map(map) => map.get(&key),
1508            _ => None,
1509        }
1510    }
1511
1512    /// Mutable version of [`get`](Self::get).
1513    ///
1514    /// ```
1515    /// use cbor_core::{Value, array};
1516    ///
1517    /// let mut a = array![10, 20, 30];
1518    /// *a.get_mut(1).unwrap() = Value::from(99);
1519    /// assert_eq!(a[1].to_u32().unwrap(), 99);
1520    /// ```
1521    pub fn get_mut(&mut self, index: impl Into<Value>) -> Option<&mut Value> {
1522        let key = index.into();
1523        match self.untagged_mut() {
1524            Value::Array(arr) => key.to_usize().ok().and_then(|i| arr.get_mut(i)),
1525            Value::Map(map) => map.get_mut(&key),
1526            _ => None,
1527        }
1528    }
1529
1530    // ------------------- Tags ------------------
1531
1532    /// Return the tag number.
1533    pub const fn tag_number(&self) -> Result<u64> {
1534        match self {
1535            Self::Tag(number, _content) => Ok(*number),
1536            _ => Err(Error::IncompatibleType(self.data_type())),
1537        }
1538    }
1539
1540    /// Borrow the tag content.
1541    pub const fn tag_content(&self) -> Result<&Self> {
1542        match self {
1543            Self::Tag(_tag, content) => Ok(content),
1544            _ => Err(Error::IncompatibleType(self.data_type())),
1545        }
1546    }
1547
1548    /// Mutably borrow the tag content.
1549    pub const fn tag_content_mut(&mut self) -> Result<&mut Self> {
1550        match self {
1551            Self::Tag(_, value) => Ok(value),
1552            _ => Err(Error::IncompatibleType(self.data_type())),
1553        }
1554    }
1555
1556    /// Borrow tag number and content together.
1557    pub fn as_tag(&self) -> Result<(u64, &Value)> {
1558        match self {
1559            Self::Tag(number, content) => Ok((*number, content)),
1560            _ => Err(Error::IncompatibleType(self.data_type())),
1561        }
1562    }
1563
1564    /// Borrow tag number and mutable content together.
1565    pub fn as_tag_mut(&mut self) -> Result<(u64, &mut Value)> {
1566        match self {
1567            Self::Tag(number, content) => Ok((*number, content)),
1568            _ => Err(Error::IncompatibleType(self.data_type())),
1569        }
1570    }
1571
1572    /// Consume self and return tag number and content.
1573    pub fn into_tag(self) -> Result<(u64, Value)> {
1574        match self {
1575            Self::Tag(number, content) => Ok((number, *content)),
1576            _ => Err(Error::IncompatibleType(self.data_type())),
1577        }
1578    }
1579
1580    /// Remove the outermost tag, returning its number. Returns `None` if
1581    /// the value is not tagged.
1582    pub fn remove_tag(&mut self) -> Option<u64> {
1583        let mut result = None;
1584        if let Self::Tag(number, content) = self {
1585            result = Some(*number);
1586            *self = std::mem::take(content);
1587        }
1588        result
1589    }
1590
1591    /// Remove all nested tags, returning their numbers from outermost to
1592    /// innermost.
1593    pub fn remove_all_tags(&mut self) -> Vec<u64> {
1594        let mut tags = Vec::new();
1595        while let Self::Tag(number, content) = self {
1596            tags.push(*number);
1597            *self = std::mem::take(content);
1598        }
1599        tags
1600    }
1601
1602    /// Skip all tag wrappers except the innermost one.
1603    /// Returns `self` unchanged if not tagged or only single-tagged.
1604    #[must_use]
1605    pub(crate) const fn peeled(&self) -> &Self {
1606        let mut result = self;
1607        while let Self::Tag(_, content) = result
1608            && content.data_type().is_tag()
1609        {
1610            result = content;
1611        }
1612        result
1613    }
1614
1615    /// Borrow the innermost non-tag value, skipping all tag wrappers.
1616    #[must_use]
1617    pub const fn untagged(&self) -> &Self {
1618        let mut result = self;
1619        while let Self::Tag(_, content) = result {
1620            result = content;
1621        }
1622        result
1623    }
1624
1625    /// Mutable version of [`untagged`](Self::untagged).
1626    pub const fn untagged_mut(&mut self) -> &mut Self {
1627        let mut result = self;
1628        while let Self::Tag(_, content) = result {
1629            result = content;
1630        }
1631        result
1632    }
1633
1634    /// Consuming version of [`untagged`](Self::untagged).
1635    #[must_use]
1636    pub fn into_untagged(mut self) -> Self {
1637        while let Self::Tag(_number, content) = self {
1638            self = *content;
1639        }
1640        self
1641    }
1642}
1643
1644// -------------------- Helpers --------------------
1645
1646fn read_vec(reader: &mut impl io::Read, len: u64) -> crate::IoResult<Vec<u8>> {
1647    use io::Read;
1648
1649    if len > LENGTH_LIMIT {
1650        return Error::LengthTooLarge.into();
1651    }
1652
1653    let len_usize = usize::try_from(len).or(Err(Error::LengthTooLarge))?;
1654    let mut buf = Vec::with_capacity(len_usize.min(OOM_MITIGATION)); // Mitigate OOM
1655    let bytes_read = reader.take(len).read_to_end(&mut buf)?;
1656
1657    if bytes_read == len_usize {
1658        Ok(buf)
1659    } else {
1660        Error::UnexpectedEof.into()
1661    }
1662}