From d1b2d29528b7794b41e66fc2136e395a02f8529b Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Thu, 30 May 2024 05:59:35 +0200 Subject: Merging upstream version 1.73.0+dfsg1. Signed-off-by: Daniel Baumann --- vendor/ciborium/src/value/mod.rs | 685 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 685 insertions(+) create mode 100644 vendor/ciborium/src/value/mod.rs (limited to 'vendor/ciborium/src/value/mod.rs') diff --git a/vendor/ciborium/src/value/mod.rs b/vendor/ciborium/src/value/mod.rs new file mode 100644 index 000000000..7233026f1 --- /dev/null +++ b/vendor/ciborium/src/value/mod.rs @@ -0,0 +1,685 @@ +// SPDX-License-Identifier: Apache-2.0 + +//! A dynamic CBOR value + +mod canonical; +mod integer; + +mod de; +mod error; +mod ser; + +pub use canonical::CanonicalValue; +pub use error::Error; +pub use integer::Integer; + +use alloc::{boxed::Box, string::String, vec::Vec}; + +/// A representation of a dynamic CBOR value that can handled dynamically +#[non_exhaustive] +#[derive(Clone, Debug, PartialEq, PartialOrd)] +pub enum Value { + /// An integer + Integer(Integer), + + /// Bytes + Bytes(Vec), + + /// A float + Float(f64), + + /// A string + Text(String), + + /// A boolean + Bool(bool), + + /// Null + Null, + + /// Tag + Tag(u64, Box), + + /// An array + Array(Vec), + + /// A map + Map(Vec<(Value, Value)>), +} + +impl Value { + /// Returns true if the `Value` is an `Integer`. Returns false otherwise. + /// + /// ``` + /// # use ciborium::Value; + /// # + /// let value = Value::Integer(17.into()); + /// + /// assert!(value.is_integer()); + /// ``` + pub fn is_integer(&self) -> bool { + self.as_integer().is_some() + } + + /// If the `Value` is a `Integer`, returns a reference to the associated `Integer` data. + /// Returns None otherwise. + /// + /// ``` + /// # use ciborium::Value; + /// # + /// let value = Value::Integer(17.into()); + /// + /// // We can read the number + /// assert_eq!(17, value.as_integer().unwrap().try_into().unwrap()); + /// ``` + pub fn as_integer(&self) -> Option { + match self { + Value::Integer(int) => Some(*int), + _ => None, + } + } + + /// If the `Value` is a `Integer`, returns a the associated `Integer` data as `Ok`. + /// Returns `Err(Self)` otherwise. + /// + /// ``` + /// # use ciborium::{Value, value::Integer}; + /// # + /// let value = Value::Integer(17.into()); + /// assert_eq!(value.into_integer(), Ok(Integer::from(17))); + /// + /// let value = Value::Bool(true); + /// assert_eq!(value.into_integer(), Err(Value::Bool(true))); + /// ``` + pub fn into_integer(self) -> Result { + match self { + Value::Integer(int) => Ok(int), + other => Err(other), + } + } + + /// Returns true if the `Value` is a `Bytes`. Returns false otherwise. + /// + /// ``` + /// # use ciborium::Value; + /// # + /// let value = Value::Bytes(vec![104, 101, 108, 108, 111]); + /// + /// assert!(value.is_bytes()); + /// ``` + pub fn is_bytes(&self) -> bool { + self.as_bytes().is_some() + } + + /// If the `Value` is a `Bytes`, returns a reference to the associated bytes vector. + /// Returns None otherwise. + /// + /// ``` + /// # use ciborium::Value; + /// # + /// let value = Value::Bytes(vec![104, 101, 108, 108, 111]); + /// + /// assert_eq!(std::str::from_utf8(value.as_bytes().unwrap()).unwrap(), "hello"); + /// ``` + pub fn as_bytes(&self) -> Option<&Vec> { + match *self { + Value::Bytes(ref bytes) => Some(bytes), + _ => None, + } + } + + /// If the `Value` is a `Bytes`, returns a mutable reference to the associated bytes vector. + /// Returns None otherwise. + /// + /// ``` + /// # use ciborium::Value; + /// # + /// let mut value = Value::Bytes(vec![104, 101, 108, 108, 111]); + /// value.as_bytes_mut().unwrap().clear(); + /// + /// assert_eq!(value, Value::Bytes(vec![])); + /// ``` + pub fn as_bytes_mut(&mut self) -> Option<&mut Vec> { + match *self { + Value::Bytes(ref mut bytes) => Some(bytes), + _ => None, + } + } + + /// If the `Value` is a `Bytes`, returns a the associated `Vec` data as `Ok`. + /// Returns `Err(Self)` otherwise. + /// + /// ``` + /// # use ciborium::Value; + /// # + /// let value = Value::Bytes(vec![104, 101, 108, 108, 111]); + /// assert_eq!(value.into_bytes(), Ok(vec![104, 101, 108, 108, 111])); + /// + /// let value = Value::Bool(true); + /// assert_eq!(value.into_bytes(), Err(Value::Bool(true))); + /// ``` + pub fn into_bytes(self) -> Result, Self> { + match self { + Value::Bytes(vec) => Ok(vec), + other => Err(other), + } + } + + /// Returns true if the `Value` is a `Float`. Returns false otherwise. + /// + /// ``` + /// # use ciborium::Value; + /// # + /// let value = Value::Float(17.0.into()); + /// + /// assert!(value.is_float()); + /// ``` + pub fn is_float(&self) -> bool { + self.as_float().is_some() + } + + /// If the `Value` is a `Float`, returns a reference to the associated float data. + /// Returns None otherwise. + /// + /// ``` + /// # use ciborium::Value; + /// # + /// let value = Value::Float(17.0.into()); + /// + /// // We can read the float number + /// assert_eq!(value.as_float().unwrap(), 17.0_f64); + /// ``` + pub fn as_float(&self) -> Option { + match *self { + Value::Float(f) => Some(f), + _ => None, + } + } + + /// If the `Value` is a `Float`, returns a the associated `f64` data as `Ok`. + /// Returns `Err(Self)` otherwise. + /// + /// ``` + /// # use ciborium::Value; + /// # + /// let value = Value::Float(17.); + /// assert_eq!(value.into_float(), Ok(17.)); + /// + /// let value = Value::Bool(true); + /// assert_eq!(value.into_float(), Err(Value::Bool(true))); + /// ``` + pub fn into_float(self) -> Result { + match self { + Value::Float(f) => Ok(f), + other => Err(other), + } + } + + /// Returns true if the `Value` is a `Text`. Returns false otherwise. + /// + /// ``` + /// # use ciborium::Value; + /// # + /// let value = Value::Text(String::from("hello")); + /// + /// assert!(value.is_text()); + /// ``` + pub fn is_text(&self) -> bool { + self.as_text().is_some() + } + + /// If the `Value` is a `Text`, returns a reference to the associated `String` data. + /// Returns None otherwise. + /// + /// ``` + /// # use ciborium::Value; + /// # + /// let value = Value::Text(String::from("hello")); + /// + /// // We can read the String + /// assert_eq!(value.as_text().unwrap(), "hello"); + /// ``` + pub fn as_text(&self) -> Option<&str> { + match *self { + Value::Text(ref s) => Some(s), + _ => None, + } + } + + /// If the `Value` is a `Text`, returns a mutable reference to the associated `String` data. + /// Returns None otherwise. + /// + /// ``` + /// # use ciborium::Value; + /// # + /// let mut value = Value::Text(String::from("hello")); + /// value.as_text_mut().unwrap().clear(); + /// + /// assert_eq!(value.as_text().unwrap(), &String::from("")); + /// ``` + pub fn as_text_mut(&mut self) -> Option<&mut String> { + match *self { + Value::Text(ref mut s) => Some(s), + _ => None, + } + } + + /// If the `Value` is a `String`, returns a the associated `String` data as `Ok`. + /// Returns `Err(Self)` otherwise. + /// + /// ``` + /// # use ciborium::Value; + /// # + /// let value = Value::Text(String::from("hello")); + /// assert_eq!(value.into_text().as_deref(), Ok("hello")); + /// + /// let value = Value::Bool(true); + /// assert_eq!(value.into_text(), Err(Value::Bool(true))); + /// ``` + pub fn into_text(self) -> Result { + match self { + Value::Text(s) => Ok(s), + other => Err(other), + } + } + + /// Returns true if the `Value` is a `Bool`. Returns false otherwise. + /// + /// ``` + /// # use ciborium::Value; + /// # + /// let value = Value::Bool(false); + /// + /// assert!(value.is_bool()); + /// ``` + pub fn is_bool(&self) -> bool { + self.as_bool().is_some() + } + + /// If the `Value` is a `Bool`, returns a copy of the associated boolean value. Returns None + /// otherwise. + /// + /// ``` + /// # use ciborium::Value; + /// # + /// let value = Value::Bool(false); + /// + /// assert_eq!(value.as_bool().unwrap(), false); + /// ``` + pub fn as_bool(&self) -> Option { + match *self { + Value::Bool(b) => Some(b), + _ => None, + } + } + + /// If the `Value` is a `Bool`, returns a the associated `bool` data as `Ok`. + /// Returns `Err(Self)` otherwise. + /// + /// ``` + /// # use ciborium::Value; + /// # + /// let value = Value::Bool(false); + /// assert_eq!(value.into_bool(), Ok(false)); + /// + /// let value = Value::Float(17.); + /// assert_eq!(value.into_bool(), Err(Value::Float(17.))); + /// ``` + pub fn into_bool(self) -> Result { + match self { + Value::Bool(b) => Ok(b), + other => Err(other), + } + } + + /// Returns true if the `Value` is a `Null`. Returns false otherwise. + /// + /// ``` + /// # use ciborium::Value; + /// # + /// let value = Value::Null; + /// + /// assert!(value.is_null()); + /// ``` + pub fn is_null(&self) -> bool { + matches!(self, Value::Null) + } + + /// Returns true if the `Value` is a `Tag`. Returns false otherwise. + /// + /// ``` + /// # use ciborium::Value; + /// # + /// let value = Value::Tag(61, Box::from(Value::Null)); + /// + /// assert!(value.is_tag()); + /// ``` + pub fn is_tag(&self) -> bool { + self.as_tag().is_some() + } + + /// If the `Value` is a `Tag`, returns the associated tag value and a reference to the tag `Value`. + /// Returns None otherwise. + /// + /// ``` + /// # use ciborium::Value; + /// # + /// let value = Value::Tag(61, Box::from(Value::Bytes(vec![104, 101, 108, 108, 111]))); + /// + /// let (tag, data) = value.as_tag().unwrap(); + /// assert_eq!(tag, 61); + /// assert_eq!(data, &Value::Bytes(vec![104, 101, 108, 108, 111])); + /// ``` + pub fn as_tag(&self) -> Option<(u64, &Value)> { + match self { + Value::Tag(tag, data) => Some((*tag, data)), + _ => None, + } + } + + /// If the `Value` is a `Tag`, returns the associated tag value and a mutable reference + /// to the tag `Value`. Returns None otherwise. + /// + /// ``` + /// # use ciborium::Value; + /// # + /// let mut value = Value::Tag(61, Box::from(Value::Bytes(vec![104, 101, 108, 108, 111]))); + /// + /// let (tag, mut data) = value.as_tag_mut().unwrap(); + /// data.as_bytes_mut().unwrap().clear(); + /// assert_eq!(tag, &61); + /// assert_eq!(data, &Value::Bytes(vec![])); + /// ``` + pub fn as_tag_mut(&mut self) -> Option<(&mut u64, &mut Value)> { + match self { + Value::Tag(tag, data) => Some((tag, data.as_mut())), + _ => None, + } + } + + /// If the `Value` is a `Tag`, returns a the associated pair of `u64` and `Box` data as `Ok`. + /// Returns `Err(Self)` otherwise. + /// + /// ``` + /// # use ciborium::Value; + /// # + /// let value = Value::Tag(7, Box::new(Value::Float(12.))); + /// assert_eq!(value.into_tag(), Ok((7, Box::new(Value::Float(12.))))); + /// + /// let value = Value::Bool(true); + /// assert_eq!(value.into_tag(), Err(Value::Bool(true))); + /// ``` + pub fn into_tag(self) -> Result<(u64, Box), Self> { + match self { + Value::Tag(tag, value) => Ok((tag, value)), + other => Err(other), + } + } + + /// Returns true if the `Value` is an Array. Returns false otherwise. + /// + /// ``` + /// # use ciborium::Value; + /// # + /// let value = Value::Array( + /// vec![ + /// Value::Text(String::from("foo")), + /// Value::Text(String::from("bar")) + /// ] + /// ); + /// + /// assert!(value.is_array()); + /// ``` + pub fn is_array(&self) -> bool { + self.as_array().is_some() + } + + /// If the `Value` is an Array, returns a reference to the associated vector. Returns None + /// otherwise. + /// + /// ``` + /// # use ciborium::Value; + /// # + /// let value = Value::Array( + /// vec![ + /// Value::Text(String::from("foo")), + /// Value::Text(String::from("bar")) + /// ] + /// ); + /// + /// // The length of `value` is 2 elements. + /// assert_eq!(value.as_array().unwrap().len(), 2); + /// ``` + pub fn as_array(&self) -> Option<&Vec> { + match *self { + Value::Array(ref array) => Some(array), + _ => None, + } + } + + /// If the `Value` is an Array, returns a mutable reference to the associated vector. + /// Returns None otherwise. + /// + /// ``` + /// # use ciborium::Value; + /// # + /// let mut value = Value::Array( + /// vec![ + /// Value::Text(String::from("foo")), + /// Value::Text(String::from("bar")) + /// ] + /// ); + /// + /// value.as_array_mut().unwrap().clear(); + /// assert_eq!(value, Value::Array(vec![])); + /// ``` + pub fn as_array_mut(&mut self) -> Option<&mut Vec> { + match *self { + Value::Array(ref mut list) => Some(list), + _ => None, + } + } + + /// If the `Value` is a `Array`, returns a the associated `Vec` data as `Ok`. + /// Returns `Err(Self)` otherwise. + /// + /// ``` + /// # use ciborium::{Value, value::Integer}; + /// # + /// let mut value = Value::Array( + /// vec![ + /// Value::Integer(17.into()), + /// Value::Float(18.), + /// ] + /// ); + /// assert_eq!(value.into_array(), Ok(vec![Value::Integer(17.into()), Value::Float(18.)])); + /// + /// let value = Value::Bool(true); + /// assert_eq!(value.into_array(), Err(Value::Bool(true))); + /// ``` + pub fn into_array(self) -> Result, Self> { + match self { + Value::Array(vec) => Ok(vec), + other => Err(other), + } + } + + /// Returns true if the `Value` is a Map. Returns false otherwise. + /// + /// ``` + /// # use ciborium::Value; + /// # + /// let value = Value::Map( + /// vec![ + /// (Value::Text(String::from("foo")), Value::Text(String::from("bar"))) + /// ] + /// ); + /// + /// assert!(value.is_map()); + /// ``` + pub fn is_map(&self) -> bool { + self.as_map().is_some() + } + + /// If the `Value` is a Map, returns a reference to the associated Map data. Returns None + /// otherwise. + /// + /// ``` + /// # use ciborium::Value; + /// # + /// let value = Value::Map( + /// vec![ + /// (Value::Text(String::from("foo")), Value::Text(String::from("bar"))) + /// ] + /// ); + /// + /// // The length of data is 1 entry (1 key/value pair). + /// assert_eq!(value.as_map().unwrap().len(), 1); + /// + /// // The content of the first element is what we expect + /// assert_eq!( + /// value.as_map().unwrap().get(0).unwrap(), + /// &(Value::Text(String::from("foo")), Value::Text(String::from("bar"))) + /// ); + /// ``` + pub fn as_map(&self) -> Option<&Vec<(Value, Value)>> { + match *self { + Value::Map(ref map) => Some(map), + _ => None, + } + } + + /// If the `Value` is a Map, returns a mutable reference to the associated Map Data. + /// Returns None otherwise. + /// + /// ``` + /// # use ciborium::Value; + /// # + /// let mut value = Value::Map( + /// vec![ + /// (Value::Text(String::from("foo")), Value::Text(String::from("bar"))) + /// ] + /// ); + /// + /// value.as_map_mut().unwrap().clear(); + /// assert_eq!(value, Value::Map(vec![])); + /// assert_eq!(value.as_map().unwrap().len(), 0); + /// ``` + pub fn as_map_mut(&mut self) -> Option<&mut Vec<(Value, Value)>> { + match *self { + Value::Map(ref mut map) => Some(map), + _ => None, + } + } + + /// If the `Value` is a `Map`, returns a the associated `Vec<(Value, Value)>` data as `Ok`. + /// Returns `Err(Self)` otherwise. + /// + /// ``` + /// # use ciborium::Value; + /// # + /// let mut value = Value::Map( + /// vec![ + /// (Value::Text(String::from("key")), Value::Float(18.)), + /// ] + /// ); + /// assert_eq!(value.into_map(), Ok(vec![(Value::Text(String::from("key")), Value::Float(18.))])); + /// + /// let value = Value::Bool(true); + /// assert_eq!(value.into_map(), Err(Value::Bool(true))); + /// ``` + pub fn into_map(self) -> Result, Self> { + match self { + Value::Map(map) => Ok(map), + other => Err(other), + } + } +} + +macro_rules! implfrom { + ($($v:ident($t:ty)),+ $(,)?) => { + $( + impl From<$t> for Value { + #[inline] + fn from(value: $t) -> Self { + Self::$v(value.into()) + } + } + )+ + }; +} + +implfrom! { + Integer(Integer), + Integer(u64), + Integer(i64), + Integer(u32), + Integer(i32), + Integer(u16), + Integer(i16), + Integer(u8), + Integer(i8), + + Bytes(Vec), + Bytes(&[u8]), + + Float(f64), + Float(f32), + + Text(String), + Text(&str), + + Bool(bool), + + Array(&[Value]), + Array(Vec), + + Map(&[(Value, Value)]), + Map(Vec<(Value, Value)>), +} + +impl From for Value { + #[inline] + fn from(value: u128) -> Self { + if let Ok(x) = Integer::try_from(value) { + return Value::Integer(x); + } + + let mut bytes = &value.to_be_bytes()[..]; + while let Some(0) = bytes.first() { + bytes = &bytes[1..]; + } + + Value::Tag(ciborium_ll::tag::BIGPOS, Value::Bytes(bytes.into()).into()) + } +} + +impl From for Value { + #[inline] + fn from(value: i128) -> Self { + if let Ok(x) = Integer::try_from(value) { + return Value::Integer(x); + } + + let (tag, raw) = match value.is_negative() { + true => (ciborium_ll::tag::BIGNEG, value as u128 ^ !0), + false => (ciborium_ll::tag::BIGPOS, value as u128), + }; + + let mut bytes = &raw.to_be_bytes()[..]; + while let Some(0) = bytes.first() { + bytes = &bytes[1..]; + } + + Value::Tag(tag, Value::Bytes(bytes.into()).into()) + } +} + +impl From for Value { + #[inline] + fn from(value: char) -> Self { + let mut v = String::with_capacity(1); + v.push(value); + Value::Text(v) + } +} -- cgit v1.2.3