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