From 36d22d82aa202bb199967e9512281e9a53db42c9 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 21:33:14 +0200 Subject: Adding upstream version 115.7.0esr. Signed-off-by: Daniel Baumann --- third_party/rust/serde_cbor/src/de.rs | 1360 ++++++++++++++++++++++++++ third_party/rust/serde_cbor/src/error.rs | 318 ++++++ third_party/rust/serde_cbor/src/lib.rs | 369 +++++++ third_party/rust/serde_cbor/src/read.rs | 637 ++++++++++++ third_party/rust/serde_cbor/src/ser.rs | 743 ++++++++++++++ third_party/rust/serde_cbor/src/tags.rs | 220 +++++ third_party/rust/serde_cbor/src/value/de.rs | 166 ++++ third_party/rust/serde_cbor/src/value/mod.rs | 156 +++ third_party/rust/serde_cbor/src/value/ser.rs | 443 +++++++++ third_party/rust/serde_cbor/src/write.rs | 175 ++++ 10 files changed, 4587 insertions(+) create mode 100644 third_party/rust/serde_cbor/src/de.rs create mode 100644 third_party/rust/serde_cbor/src/error.rs create mode 100644 third_party/rust/serde_cbor/src/lib.rs create mode 100644 third_party/rust/serde_cbor/src/read.rs create mode 100644 third_party/rust/serde_cbor/src/ser.rs create mode 100644 third_party/rust/serde_cbor/src/tags.rs create mode 100644 third_party/rust/serde_cbor/src/value/de.rs create mode 100644 third_party/rust/serde_cbor/src/value/mod.rs create mode 100644 third_party/rust/serde_cbor/src/value/ser.rs create mode 100644 third_party/rust/serde_cbor/src/write.rs (limited to 'third_party/rust/serde_cbor/src') diff --git a/third_party/rust/serde_cbor/src/de.rs b/third_party/rust/serde_cbor/src/de.rs new file mode 100644 index 0000000000..170e0593cf --- /dev/null +++ b/third_party/rust/serde_cbor/src/de.rs @@ -0,0 +1,1360 @@ +//! Deserialization. + +use core::f32; +use core::marker::PhantomData; +use core::result; +use core::str; +use half::f16; +use serde::de; +#[cfg(feature = "std")] +use std::io; + +use crate::error::{Error, ErrorCode, Result}; +#[cfg(not(feature = "unsealed_read_write"))] +use crate::read::EitherLifetime; +#[cfg(feature = "unsealed_read_write")] +pub use crate::read::EitherLifetime; +#[cfg(feature = "std")] +pub use crate::read::IoRead; +use crate::read::Offset; +#[cfg(any(feature = "std", feature = "alloc"))] +pub use crate::read::SliceRead; +pub use crate::read::{MutSliceRead, Read, SliceReadFixed}; +#[cfg(feature = "tags")] +use crate::tags::set_tag; +/// Decodes a value from CBOR data in a slice. +/// +/// # Examples +/// +/// Deserialize a `String` +/// +/// ``` +/// # use serde_cbor::de; +/// let v: Vec = vec![0x66, 0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72]; +/// let value: String = de::from_slice(&v[..]).unwrap(); +/// assert_eq!(value, "foobar"); +/// ``` +/// +/// Deserialize a borrowed string with zero copies. +/// +/// ``` +/// # use serde_cbor::de; +/// let v: Vec = vec![0x66, 0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72]; +/// let value: &str = de::from_slice(&v[..]).unwrap(); +/// assert_eq!(value, "foobar"); +/// ``` +#[cfg(any(feature = "std", feature = "alloc"))] +pub fn from_slice<'a, T>(slice: &'a [u8]) -> Result +where + T: de::Deserialize<'a>, +{ + let mut deserializer = Deserializer::from_slice(slice); + let value = de::Deserialize::deserialize(&mut deserializer)?; + deserializer.end()?; + Ok(value) +} + +// When the "std" feature is enabled there should be little to no need to ever use this function, +// as `from_slice` covers all use cases (at the expense of being less efficient). +/// Decode a value from CBOR data in a mutable slice. +/// +/// This can be used in analogy to `from_slice`. Unlike `from_slice`, this will use the slice's +/// mutability to rearrange data in it in order to resolve indefinite byte or text strings without +/// resorting to allocations. +pub fn from_mut_slice<'a, T>(slice: &'a mut [u8]) -> Result +where + T: de::Deserialize<'a>, +{ + let mut deserializer = Deserializer::from_mut_slice(slice); + let value = de::Deserialize::deserialize(&mut deserializer)?; + deserializer.end()?; + Ok(value) +} + +// When the "std" feature is enabled there should be little to no need to ever use this function, +// as `from_slice` covers all use cases and is much more reliable (at the expense of being less +// efficient). +/// Decode a value from CBOR data using a scratch buffer. +/// +/// Users should generally prefer to use `from_slice` or `from_mut_slice` over this function, +/// as decoding may fail when the scratch buffer turns out to be too small. +/// +/// A realistic use case for this method would be decoding in a `no_std` environment from an +/// immutable slice that is too large to copy. +pub fn from_slice_with_scratch<'a, 'b, T>(slice: &'a [u8], scratch: &'b mut [u8]) -> Result +where + T: de::Deserialize<'a>, +{ + let mut deserializer = Deserializer::from_slice_with_scratch(slice, scratch); + let value = de::Deserialize::deserialize(&mut deserializer)?; + deserializer.end()?; + Ok(value) +} + +/// Decodes a value from CBOR data in a reader. +/// +/// # Examples +/// +/// Deserialize a `String` +/// +/// ``` +/// # use serde_cbor::de; +/// let v: Vec = vec![0x66, 0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72]; +/// let value: String = de::from_reader(&v[..]).unwrap(); +/// assert_eq!(value, "foobar"); +/// ``` +/// +/// Note that `from_reader` cannot borrow data: +/// +/// ```compile_fail +/// # use serde_cbor::de; +/// let v: Vec = vec![0x66, 0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72]; +/// let value: &str = de::from_reader(&v[..]).unwrap(); +/// assert_eq!(value, "foobar"); +/// ``` +#[cfg(feature = "std")] +pub fn from_reader(reader: R) -> Result +where + T: de::DeserializeOwned, + R: io::Read, +{ + let mut deserializer = Deserializer::from_reader(reader); + let value = de::Deserialize::deserialize(&mut deserializer)?; + deserializer.end()?; + Ok(value) +} + +/// A Serde `Deserialize`r of CBOR data. +#[derive(Debug)] +pub struct Deserializer { + read: R, + remaining_depth: u8, + accept_named: bool, + accept_packed: bool, + accept_standard_enums: bool, + accept_legacy_enums: bool, +} + +#[cfg(feature = "std")] +impl Deserializer> +where + R: io::Read, +{ + /// Constructs a `Deserializer` which reads from a `Read`er. + pub fn from_reader(reader: R) -> Deserializer> { + Deserializer::new(IoRead::new(reader)) + } +} + +#[cfg(any(feature = "std", feature = "alloc"))] +impl<'a> Deserializer> { + /// Constructs a `Deserializer` which reads from a slice. + /// + /// Borrowed strings and byte slices will be provided when possible. + pub fn from_slice(bytes: &'a [u8]) -> Deserializer> { + Deserializer::new(SliceRead::new(bytes)) + } +} + +impl<'a> Deserializer> { + /// Constructs a `Deserializer` which reads from a mutable slice that doubles as its own + /// scratch buffer. + /// + /// Borrowed strings and byte slices will be provided even for indefinite strings. + pub fn from_mut_slice(bytes: &'a mut [u8]) -> Deserializer> { + Deserializer::new(MutSliceRead::new(bytes)) + } +} + +impl<'a, 'b> Deserializer> { + #[doc(hidden)] + pub fn from_slice_with_scratch( + bytes: &'a [u8], + scratch: &'b mut [u8], + ) -> Deserializer> { + Deserializer::new(SliceReadFixed::new(bytes, scratch)) + } +} + +impl<'de, R> Deserializer +where + R: Read<'de>, +{ + /// Constructs a `Deserializer` from one of the possible serde_cbor input sources. + /// + /// `from_slice` and `from_reader` should normally be used instead of this method. + pub fn new(read: R) -> Self { + Deserializer { + read, + remaining_depth: 128, + accept_named: true, + accept_packed: true, + accept_standard_enums: true, + accept_legacy_enums: true, + } + } + + /// Don't accept named variants and fields. + pub fn disable_named_format(mut self) -> Self { + self.accept_named = false; + self + } + + /// Don't accept numbered variants and fields. + pub fn disable_packed_format(mut self) -> Self { + self.accept_packed = false; + self + } + + /// Don't accept the new enum format used by `serde_cbor` versions >= v0.10. + pub fn disable_standard_enums(mut self) -> Self { + self.accept_standard_enums = false; + self + } + + /// Don't accept the old enum format used by `serde_cbor` versions <= v0.9. + pub fn disable_legacy_enums(mut self) -> Self { + self.accept_legacy_enums = false; + self + } + + /// This method should be called after a value has been deserialized to ensure there is no + /// trailing data in the input source. + pub fn end(&mut self) -> Result<()> { + match self.next()? { + Some(_) => Err(self.error(ErrorCode::TrailingData)), + None => Ok(()), + } + } + + /// Turn a CBOR deserializer into an iterator over values of type T. + #[allow(clippy::should_implement_trait)] // Trait doesn't allow unconstrained T. + pub fn into_iter(self) -> StreamDeserializer<'de, R, T> + where + T: de::Deserialize<'de>, + { + StreamDeserializer { + de: self, + output: PhantomData, + lifetime: PhantomData, + } + } + + fn next(&mut self) -> Result> { + self.read.next() + } + + fn peek(&mut self) -> Result> { + self.read.peek() + } + + fn consume(&mut self) { + self.read.discard(); + } + + fn error(&self, reason: ErrorCode) -> Error { + let offset = self.read.offset(); + Error::syntax(reason, offset) + } + + fn parse_u8(&mut self) -> Result { + match self.next()? { + Some(byte) => Ok(byte), + None => Err(self.error(ErrorCode::EofWhileParsingValue)), + } + } + + fn parse_u16(&mut self) -> Result { + let mut buf = [0; 2]; + self.read + .read_into(&mut buf) + .map(|()| u16::from_be_bytes(buf)) + } + + fn parse_u32(&mut self) -> Result { + let mut buf = [0; 4]; + self.read + .read_into(&mut buf) + .map(|()| u32::from_be_bytes(buf)) + } + + fn parse_u64(&mut self) -> Result { + let mut buf = [0; 8]; + self.read + .read_into(&mut buf) + .map(|()| u64::from_be_bytes(buf)) + } + + fn parse_bytes(&mut self, len: usize, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + match self.read.read(len)? { + EitherLifetime::Long(buf) => visitor.visit_borrowed_bytes(buf), + EitherLifetime::Short(buf) => visitor.visit_bytes(buf), + } + } + + fn parse_indefinite_bytes(&mut self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + self.read.clear_buffer(); + loop { + let byte = self.parse_u8()?; + let len = match byte { + 0x40..=0x57 => byte as usize - 0x40, + 0x58 => self.parse_u8()? as usize, + 0x59 => self.parse_u16()? as usize, + 0x5a => self.parse_u32()? as usize, + 0x5b => { + let len = self.parse_u64()?; + if len > usize::max_value() as u64 { + return Err(self.error(ErrorCode::LengthOutOfRange)); + } + len as usize + } + 0xff => break, + _ => return Err(self.error(ErrorCode::UnexpectedCode)), + }; + + self.read.read_to_buffer(len)?; + } + + match self.read.take_buffer() { + EitherLifetime::Long(buf) => visitor.visit_borrowed_bytes(buf), + EitherLifetime::Short(buf) => visitor.visit_bytes(buf), + } + } + + fn convert_str<'a>(buf: &'a [u8], buf_end_offset: u64) -> Result<&'a str> { + match str::from_utf8(buf) { + Ok(s) => Ok(s), + Err(e) => { + let shift = buf.len() - e.valid_up_to(); + let offset = buf_end_offset - shift as u64; + Err(Error::syntax(ErrorCode::InvalidUtf8, offset)) + } + } + } + + fn parse_str(&mut self, len: usize, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + if let Some(offset) = self.read.offset().checked_add(len as u64) { + match self.read.read(len)? { + EitherLifetime::Long(buf) => { + let s = Self::convert_str(buf, offset)?; + visitor.visit_borrowed_str(s) + } + EitherLifetime::Short(buf) => { + let s = Self::convert_str(buf, offset)?; + visitor.visit_str(s) + } + } + } else { + // An overflow would have occured. + Err(Error::syntax( + ErrorCode::LengthOutOfRange, + self.read.offset(), + )) + } + } + + fn parse_indefinite_str(&mut self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + self.read.clear_buffer(); + loop { + let byte = self.parse_u8()?; + let len = match byte { + 0x60..=0x77 => byte as usize - 0x60, + 0x78 => self.parse_u8()? as usize, + 0x79 => self.parse_u16()? as usize, + 0x7a => self.parse_u32()? as usize, + 0x7b => { + let len = self.parse_u64()?; + if len > usize::max_value() as u64 { + return Err(self.error(ErrorCode::LengthOutOfRange)); + } + len as usize + } + 0xff => break, + _ => return Err(self.error(ErrorCode::UnexpectedCode)), + }; + + self.read.read_to_buffer(len)?; + } + + let offset = self.read.offset(); + match self.read.take_buffer() { + EitherLifetime::Long(buf) => { + let s = Self::convert_str(buf, offset)?; + visitor.visit_borrowed_str(s) + } + EitherLifetime::Short(buf) => { + let s = Self::convert_str(buf, offset)?; + visitor.visit_str(s) + } + } + } + + #[cfg(feature = "tags")] + fn handle_tagged_value(&mut self, tag: u64, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + self.recursion_checked(|d| { + set_tag(Some(tag)); + let r = visitor.visit_newtype_struct(d); + set_tag(None); + r + }) + } + + #[cfg(not(feature = "tags"))] + fn handle_tagged_value(&mut self, _tag: u64, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + self.recursion_checked(|de| de.parse_value(visitor)) + } + + fn recursion_checked(&mut self, f: F) -> Result + where + F: FnOnce(&mut Deserializer) -> Result, + { + self.remaining_depth -= 1; + if self.remaining_depth == 0 { + return Err(self.error(ErrorCode::RecursionLimitExceeded)); + } + let r = f(self); + self.remaining_depth += 1; + r + } + + fn parse_array(&mut self, mut len: usize, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + self.recursion_checked(|de| { + let value = visitor.visit_seq(SeqAccess { de, len: &mut len })?; + + if len != 0 { + Err(de.error(ErrorCode::TrailingData)) + } else { + Ok(value) + } + }) + } + + fn parse_indefinite_array(&mut self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + self.recursion_checked(|de| { + let value = visitor.visit_seq(IndefiniteSeqAccess { de })?; + match de.next()? { + Some(0xff) => Ok(value), + Some(_) => Err(de.error(ErrorCode::TrailingData)), + None => Err(de.error(ErrorCode::EofWhileParsingArray)), + } + }) + } + + fn parse_map(&mut self, mut len: usize, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + let accept_packed = self.accept_packed; + let accept_named = self.accept_named; + self.recursion_checked(|de| { + let value = visitor.visit_map(MapAccess { + de, + len: &mut len, + accept_named, + accept_packed, + })?; + + if len != 0 { + Err(de.error(ErrorCode::TrailingData)) + } else { + Ok(value) + } + }) + } + + fn parse_indefinite_map(&mut self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + let accept_named = self.accept_named; + let accept_packed = self.accept_packed; + self.recursion_checked(|de| { + let value = visitor.visit_map(IndefiniteMapAccess { + de, + accept_packed, + accept_named, + })?; + match de.next()? { + Some(0xff) => Ok(value), + Some(_) => Err(de.error(ErrorCode::TrailingData)), + None => Err(de.error(ErrorCode::EofWhileParsingMap)), + } + }) + } + + fn parse_enum(&mut self, mut len: usize, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + self.recursion_checked(|de| { + let value = visitor.visit_enum(VariantAccess { + seq: SeqAccess { de, len: &mut len }, + })?; + + if len != 0 { + Err(de.error(ErrorCode::TrailingData)) + } else { + Ok(value) + } + }) + } + + fn parse_enum_map(&mut self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + let accept_named = self.accept_named; + let accept_packed = self.accept_packed; + self.recursion_checked(|de| { + let mut len = 1; + let value = visitor.visit_enum(VariantAccessMap { + map: MapAccess { + de, + len: &mut len, + accept_packed, + accept_named, + }, + })?; + + if len != 0 { + Err(de.error(ErrorCode::TrailingData)) + } else { + Ok(value) + } + }) + } + + fn parse_indefinite_enum(&mut self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + self.recursion_checked(|de| { + let value = visitor.visit_enum(VariantAccess { + seq: IndefiniteSeqAccess { de }, + })?; + match de.next()? { + Some(0xff) => Ok(value), + Some(_) => Err(de.error(ErrorCode::TrailingData)), + None => Err(de.error(ErrorCode::EofWhileParsingArray)), + } + }) + } + + fn parse_f16(&mut self) -> Result { + Ok(f32::from(f16::from_bits(self.parse_u16()?))) + } + + fn parse_f32(&mut self) -> Result { + self.parse_u32().map(|i| f32::from_bits(i)) + } + + fn parse_f64(&mut self) -> Result { + self.parse_u64().map(|i| f64::from_bits(i)) + } + + // Don't warn about the `unreachable!` in case + // exhaustive integer pattern matching is enabled. + #[allow(unreachable_patterns)] + fn parse_value(&mut self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + let byte = self.parse_u8()?; + match byte { + // Major type 0: an unsigned integer + 0x00..=0x17 => visitor.visit_u8(byte), + 0x18 => { + let value = self.parse_u8()?; + visitor.visit_u8(value) + } + 0x19 => { + let value = self.parse_u16()?; + visitor.visit_u16(value) + } + 0x1a => { + let value = self.parse_u32()?; + visitor.visit_u32(value) + } + 0x1b => { + let value = self.parse_u64()?; + visitor.visit_u64(value) + } + 0x1c..=0x1f => Err(self.error(ErrorCode::UnassignedCode)), + + // Major type 1: a negative integer + 0x20..=0x37 => visitor.visit_i8(-1 - (byte - 0x20) as i8), + 0x38 => { + let value = self.parse_u8()?; + visitor.visit_i16(-1 - i16::from(value)) + } + 0x39 => { + let value = self.parse_u16()?; + visitor.visit_i32(-1 - i32::from(value)) + } + 0x3a => { + let value = self.parse_u32()?; + visitor.visit_i64(-1 - i64::from(value)) + } + 0x3b => { + let value = self.parse_u64()?; + if value > i64::max_value() as u64 { + return visitor.visit_i128(-1 - i128::from(value)); + } + visitor.visit_i64(-1 - value as i64) + } + 0x3c..=0x3f => Err(self.error(ErrorCode::UnassignedCode)), + + // Major type 2: a byte string + 0x40..=0x57 => self.parse_bytes(byte as usize - 0x40, visitor), + 0x58 => { + let len = self.parse_u8()?; + self.parse_bytes(len as usize, visitor) + } + 0x59 => { + let len = self.parse_u16()?; + self.parse_bytes(len as usize, visitor) + } + 0x5a => { + let len = self.parse_u32()?; + self.parse_bytes(len as usize, visitor) + } + 0x5b => { + let len = self.parse_u64()?; + if len > usize::max_value() as u64 { + return Err(self.error(ErrorCode::LengthOutOfRange)); + } + self.parse_bytes(len as usize, visitor) + } + 0x5c..=0x5e => Err(self.error(ErrorCode::UnassignedCode)), + 0x5f => self.parse_indefinite_bytes(visitor), + + // Major type 3: a text string + 0x60..=0x77 => self.parse_str(byte as usize - 0x60, visitor), + 0x78 => { + let len = self.parse_u8()?; + self.parse_str(len as usize, visitor) + } + 0x79 => { + let len = self.parse_u16()?; + self.parse_str(len as usize, visitor) + } + 0x7a => { + let len = self.parse_u32()?; + self.parse_str(len as usize, visitor) + } + 0x7b => { + let len = self.parse_u64()?; + if len > usize::max_value() as u64 { + return Err(self.error(ErrorCode::LengthOutOfRange)); + } + self.parse_str(len as usize, visitor) + } + 0x7c..=0x7e => Err(self.error(ErrorCode::UnassignedCode)), + 0x7f => self.parse_indefinite_str(visitor), + + // Major type 4: an array of data items + 0x80..=0x97 => self.parse_array(byte as usize - 0x80, visitor), + 0x98 => { + let len = self.parse_u8()?; + self.parse_array(len as usize, visitor) + } + 0x99 => { + let len = self.parse_u16()?; + self.parse_array(len as usize, visitor) + } + 0x9a => { + let len = self.parse_u32()?; + self.parse_array(len as usize, visitor) + } + 0x9b => { + let len = self.parse_u64()?; + if len > usize::max_value() as u64 { + return Err(self.error(ErrorCode::LengthOutOfRange)); + } + self.parse_array(len as usize, visitor) + } + 0x9c..=0x9e => Err(self.error(ErrorCode::UnassignedCode)), + 0x9f => self.parse_indefinite_array(visitor), + + // Major type 5: a map of pairs of data items + 0xa0..=0xb7 => self.parse_map(byte as usize - 0xa0, visitor), + 0xb8 => { + let len = self.parse_u8()?; + self.parse_map(len as usize, visitor) + } + 0xb9 => { + let len = self.parse_u16()?; + self.parse_map(len as usize, visitor) + } + 0xba => { + let len = self.parse_u32()?; + self.parse_map(len as usize, visitor) + } + 0xbb => { + let len = self.parse_u64()?; + if len > usize::max_value() as u64 { + return Err(self.error(ErrorCode::LengthOutOfRange)); + } + self.parse_map(len as usize, visitor) + } + 0xbc..=0xbe => Err(self.error(ErrorCode::UnassignedCode)), + 0xbf => self.parse_indefinite_map(visitor), + + // Major type 6: optional semantic tagging of other major types + 0xc0..=0xd7 => { + let tag = u64::from(byte) - 0xc0; + self.handle_tagged_value(tag, visitor) + } + 0xd8 => { + let tag = self.parse_u8()?; + self.handle_tagged_value(tag.into(), visitor) + } + 0xd9 => { + let tag = self.parse_u16()?; + self.handle_tagged_value(tag.into(), visitor) + } + 0xda => { + let tag = self.parse_u32()?; + self.handle_tagged_value(tag.into(), visitor) + } + 0xdb => { + let tag = self.parse_u64()?; + self.handle_tagged_value(tag, visitor) + } + 0xdc..=0xdf => Err(self.error(ErrorCode::UnassignedCode)), + + // Major type 7: floating-point numbers and other simple data types that need no content + 0xe0..=0xf3 => Err(self.error(ErrorCode::UnassignedCode)), + 0xf4 => visitor.visit_bool(false), + 0xf5 => visitor.visit_bool(true), + 0xf6 => visitor.visit_unit(), + 0xf7 => visitor.visit_unit(), + 0xf8 => Err(self.error(ErrorCode::UnassignedCode)), + 0xf9 => { + let value = self.parse_f16()?; + visitor.visit_f32(value) + } + 0xfa => { + let value = self.parse_f32()?; + visitor.visit_f32(value) + } + 0xfb => { + let value = self.parse_f64()?; + visitor.visit_f64(value) + } + 0xfc..=0xfe => Err(self.error(ErrorCode::UnassignedCode)), + 0xff => Err(self.error(ErrorCode::UnexpectedCode)), + + _ => unreachable!(), + } + } +} + +impl<'de, 'a, R> de::Deserializer<'de> for &'a mut Deserializer +where + R: Read<'de>, +{ + type Error = Error; + + #[inline] + fn deserialize_any(self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + self.parse_value(visitor) + } + + #[inline] + fn deserialize_option(self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + match self.peek()? { + Some(0xf6) => { + self.consume(); + visitor.visit_none() + } + _ => visitor.visit_some(self), + } + } + + #[inline] + fn deserialize_newtype_struct(self, _name: &str, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + visitor.visit_newtype_struct(self) + } + + // Unit variants are encoded as just the variant identifier. + // Tuple variants are encoded as an array of the variant identifier followed by the fields. + // Struct variants are encoded as an array of the variant identifier followed by the struct. + #[inline] + fn deserialize_enum( + self, + _name: &str, + _variants: &'static [&'static str], + visitor: V, + ) -> Result + where + V: de::Visitor<'de>, + { + match self.peek()? { + Some(byte @ 0x80..=0x9f) => { + if !self.accept_legacy_enums { + return Err(self.error(ErrorCode::WrongEnumFormat)); + } + self.consume(); + match byte { + 0x80..=0x97 => self.parse_enum(byte as usize - 0x80, visitor), + 0x98 => { + let len = self.parse_u8()?; + self.parse_enum(len as usize, visitor) + } + 0x99 => { + let len = self.parse_u16()?; + self.parse_enum(len as usize, visitor) + } + 0x9a => { + let len = self.parse_u32()?; + self.parse_enum(len as usize, visitor) + } + 0x9b => { + let len = self.parse_u64()?; + if len > usize::max_value() as u64 { + return Err(self.error(ErrorCode::LengthOutOfRange)); + } + self.parse_enum(len as usize, visitor) + } + 0x9c..=0x9e => Err(self.error(ErrorCode::UnassignedCode)), + 0x9f => self.parse_indefinite_enum(visitor), + + _ => unreachable!(), + } + } + Some(0xa1) => { + if !self.accept_standard_enums { + return Err(self.error(ErrorCode::WrongEnumFormat)); + } + self.consume(); + self.parse_enum_map(visitor) + } + None => Err(self.error(ErrorCode::EofWhileParsingValue)), + _ => { + if !self.accept_standard_enums && !self.accept_legacy_enums { + return Err(self.error(ErrorCode::WrongEnumFormat)); + } + visitor.visit_enum(UnitVariantAccess { de: self }) + } + } + } + + #[inline] + fn is_human_readable(&self) -> bool { + false + } + + serde::forward_to_deserialize_any! { + bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string unit + unit_struct seq tuple tuple_struct map struct identifier ignored_any + bytes byte_buf + } +} + +impl Deserializer +where + R: Offset, +{ + /// Return the current offset in the reader + #[inline] + pub fn byte_offset(&self) -> usize { + self.read.byte_offset() + } +} + +trait MakeError { + fn error(&self, code: ErrorCode) -> Error; +} + +struct SeqAccess<'a, R> { + de: &'a mut Deserializer, + len: &'a mut usize, +} + +impl<'de, 'a, R> de::SeqAccess<'de> for SeqAccess<'a, R> +where + R: Read<'de>, +{ + type Error = Error; + + fn next_element_seed(&mut self, seed: T) -> Result> + where + T: de::DeserializeSeed<'de>, + { + if *self.len == 0 { + return Ok(None); + } + *self.len -= 1; + + let value = seed.deserialize(&mut *self.de)?; + Ok(Some(value)) + } + + fn size_hint(&self) -> Option { + Some(*self.len) + } +} + +impl<'de, 'a, R> MakeError for SeqAccess<'a, R> +where + R: Read<'de>, +{ + fn error(&self, code: ErrorCode) -> Error { + self.de.error(code) + } +} + +struct IndefiniteSeqAccess<'a, R> { + de: &'a mut Deserializer, +} + +impl<'de, 'a, R> de::SeqAccess<'de> for IndefiniteSeqAccess<'a, R> +where + R: Read<'de>, +{ + type Error = Error; + + fn next_element_seed(&mut self, seed: T) -> Result> + where + T: de::DeserializeSeed<'de>, + { + match self.de.peek()? { + Some(0xff) => return Ok(None), + Some(_) => {} + None => return Err(self.de.error(ErrorCode::EofWhileParsingArray)), + } + + let value = seed.deserialize(&mut *self.de)?; + Ok(Some(value)) + } +} + +impl<'de, 'a, R> MakeError for IndefiniteSeqAccess<'a, R> +where + R: Read<'de>, +{ + fn error(&self, code: ErrorCode) -> Error { + self.de.error(code) + } +} + +struct MapAccess<'a, R> { + de: &'a mut Deserializer, + len: &'a mut usize, + accept_named: bool, + accept_packed: bool, +} + +impl<'de, 'a, R> de::MapAccess<'de> for MapAccess<'a, R> +where + R: Read<'de>, +{ + type Error = Error; + + fn next_key_seed(&mut self, seed: K) -> Result> + where + K: de::DeserializeSeed<'de>, + { + if *self.len == 0 { + return Ok(None); + } + *self.len -= 1; + + match self.de.peek()? { + Some(_byte @ 0x00..=0x1b) if !self.accept_packed => { + return Err(self.de.error(ErrorCode::WrongStructFormat)); + } + Some(_byte @ 0x60..=0x7f) if !self.accept_named => { + return Err(self.de.error(ErrorCode::WrongStructFormat)); + } + _ => {} + }; + + let value = seed.deserialize(&mut *self.de)?; + Ok(Some(value)) + } + + fn next_value_seed(&mut self, seed: V) -> Result + where + V: de::DeserializeSeed<'de>, + { + seed.deserialize(&mut *self.de) + } + + fn size_hint(&self) -> Option { + Some(*self.len) + } +} + +impl<'de, 'a, R> MakeError for MapAccess<'a, R> +where + R: Read<'de>, +{ + fn error(&self, code: ErrorCode) -> Error { + self.de.error(code) + } +} + +struct IndefiniteMapAccess<'a, R> { + de: &'a mut Deserializer, + accept_packed: bool, + accept_named: bool, +} + +impl<'de, 'a, R> de::MapAccess<'de> for IndefiniteMapAccess<'a, R> +where + R: Read<'de>, +{ + type Error = Error; + + fn next_key_seed(&mut self, seed: K) -> Result> + where + K: de::DeserializeSeed<'de>, + { + match self.de.peek()? { + Some(_byte @ 0x00..=0x1b) if !self.accept_packed => { + return Err(self.de.error(ErrorCode::WrongStructFormat)) + } + Some(_byte @ 0x60..=0x7f) if !self.accept_named => { + return Err(self.de.error(ErrorCode::WrongStructFormat)) + } + Some(0xff) => return Ok(None), + Some(_) => {} + None => return Err(self.de.error(ErrorCode::EofWhileParsingMap)), + } + + let value = seed.deserialize(&mut *self.de)?; + Ok(Some(value)) + } + + fn next_value_seed(&mut self, seed: V) -> Result + where + V: de::DeserializeSeed<'de>, + { + seed.deserialize(&mut *self.de) + } +} + +struct UnitVariantAccess<'a, R> { + de: &'a mut Deserializer, +} + +impl<'de, 'a, R> de::EnumAccess<'de> for UnitVariantAccess<'a, R> +where + R: Read<'de>, +{ + type Error = Error; + type Variant = UnitVariantAccess<'a, R>; + + fn variant_seed(self, seed: V) -> Result<(V::Value, UnitVariantAccess<'a, R>)> + where + V: de::DeserializeSeed<'de>, + { + let variant = seed.deserialize(&mut *self.de)?; + Ok((variant, self)) + } +} + +impl<'de, 'a, R> de::VariantAccess<'de> for UnitVariantAccess<'a, R> +where + R: Read<'de>, +{ + type Error = Error; + + fn unit_variant(self) -> Result<()> { + Ok(()) + } + + fn newtype_variant_seed(self, _seed: T) -> Result + where + T: de::DeserializeSeed<'de>, + { + Err(de::Error::invalid_type( + de::Unexpected::UnitVariant, + &"newtype variant", + )) + } + + fn tuple_variant(self, _len: usize, _visitor: V) -> Result + where + V: de::Visitor<'de>, + { + Err(de::Error::invalid_type( + de::Unexpected::UnitVariant, + &"tuple variant", + )) + } + + fn struct_variant(self, _fields: &'static [&'static str], _visitor: V) -> Result + where + V: de::Visitor<'de>, + { + Err(de::Error::invalid_type( + de::Unexpected::UnitVariant, + &"struct variant", + )) + } +} + +struct VariantAccess { + seq: T, +} + +impl<'de, T> de::EnumAccess<'de> for VariantAccess +where + T: de::SeqAccess<'de, Error = Error> + MakeError, +{ + type Error = Error; + type Variant = VariantAccess; + + fn variant_seed(mut self, seed: V) -> Result<(V::Value, VariantAccess)> + where + V: de::DeserializeSeed<'de>, + { + let variant = match self.seq.next_element_seed(seed) { + Ok(Some(variant)) => variant, + Ok(None) => return Err(self.seq.error(ErrorCode::ArrayTooShort)), + Err(e) => return Err(e), + }; + Ok((variant, self)) + } +} + +impl<'de, T> de::VariantAccess<'de> for VariantAccess +where + T: de::SeqAccess<'de, Error = Error> + MakeError, +{ + type Error = Error; + + fn unit_variant(mut self) -> Result<()> { + match self.seq.next_element() { + Ok(Some(())) => Ok(()), + Ok(None) => Err(self.seq.error(ErrorCode::ArrayTooLong)), + Err(e) => Err(e), + } + } + + fn newtype_variant_seed(mut self, seed: S) -> Result + where + S: de::DeserializeSeed<'de>, + { + match self.seq.next_element_seed(seed) { + Ok(Some(variant)) => Ok(variant), + Ok(None) => Err(self.seq.error(ErrorCode::ArrayTooShort)), + Err(e) => Err(e), + } + } + + fn tuple_variant(self, _len: usize, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + visitor.visit_seq(self.seq) + } + + fn struct_variant(mut self, _fields: &'static [&'static str], visitor: V) -> Result + where + V: de::Visitor<'de>, + { + let seed = StructVariantSeed { visitor }; + match self.seq.next_element_seed(seed) { + Ok(Some(variant)) => Ok(variant), + Ok(None) => Err(self.seq.error(ErrorCode::ArrayTooShort)), + Err(e) => Err(e), + } + } +} + +struct StructVariantSeed { + visitor: V, +} + +impl<'de, V> de::DeserializeSeed<'de> for StructVariantSeed +where + V: de::Visitor<'de>, +{ + type Value = V::Value; + + fn deserialize(self, de: D) -> result::Result + where + D: de::Deserializer<'de>, + { + de.deserialize_any(self.visitor) + } +} + +/// Iterator that deserializes a stream into multiple CBOR values. +/// +/// A stream deserializer can be created from any CBOR deserializer using the +/// `Deserializer::into_iter` method. +/// +/// ``` +/// # extern crate serde_cbor; +/// use serde_cbor::de::Deserializer; +/// use serde_cbor::value::Value; +/// +/// # fn main() { +/// let data: Vec = vec![ +/// 0x01, 0x66, 0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72, +/// ]; +/// let mut it = Deserializer::from_slice(&data[..]).into_iter::(); +/// assert_eq!( +/// Value::Integer(1), +/// it.next().unwrap().unwrap() +/// ); +/// assert_eq!( +/// Value::Text("foobar".to_string()), +/// it.next().unwrap().unwrap() +/// ); +/// # } +/// ``` +#[derive(Debug)] +pub struct StreamDeserializer<'de, R, T> { + de: Deserializer, + output: PhantomData, + lifetime: PhantomData<&'de ()>, +} + +impl<'de, R, T> StreamDeserializer<'de, R, T> +where + R: Read<'de>, + T: de::Deserialize<'de>, +{ + /// Create a new CBOR stream deserializer from one of the possible + /// serde_cbor input sources. + /// + /// Typically it is more convenient to use one of these methods instead: + /// + /// * `Deserializer::from_slice(...).into_iter()` + /// * `Deserializer::from_reader(...).into_iter()` + pub fn new(read: R) -> StreamDeserializer<'de, R, T> { + StreamDeserializer { + de: Deserializer::new(read), + output: PhantomData, + lifetime: PhantomData, + } + } +} + +impl<'de, R, T> StreamDeserializer<'de, R, T> +where + R: Offset, + T: de::Deserialize<'de>, +{ + /// Return the current offset in the reader + #[inline] + pub fn byte_offset(&self) -> usize { + self.de.byte_offset() + } +} + +impl<'de, R, T> Iterator for StreamDeserializer<'de, R, T> +where + R: Read<'de>, + T: de::Deserialize<'de>, +{ + type Item = Result; + + fn next(&mut self) -> Option> { + match self.de.peek() { + Ok(Some(_)) => Some(T::deserialize(&mut self.de)), + Ok(None) => None, + Err(e) => Some(Err(e)), + } + } +} + +struct VariantAccessMap { + map: T, +} + +impl<'de, T> de::EnumAccess<'de> for VariantAccessMap +where + T: de::MapAccess<'de, Error = Error> + MakeError, +{ + type Error = Error; + type Variant = VariantAccessMap; + + fn variant_seed(mut self, seed: V) -> Result<(V::Value, VariantAccessMap)> + where + V: de::DeserializeSeed<'de>, + { + let variant = match self.map.next_key_seed(seed) { + Ok(Some(variant)) => variant, + Ok(None) => return Err(self.map.error(ErrorCode::ArrayTooShort)), + Err(e) => return Err(e), + }; + Ok((variant, self)) + } +} + +impl<'de, T> de::VariantAccess<'de> for VariantAccessMap +where + T: de::MapAccess<'de, Error = Error> + MakeError, +{ + type Error = Error; + + fn unit_variant(mut self) -> Result<()> { + match self.map.next_value() { + Ok(()) => Ok(()), + Err(e) => Err(e), + } + } + + fn newtype_variant_seed(mut self, seed: S) -> Result + where + S: de::DeserializeSeed<'de>, + { + self.map.next_value_seed(seed) + } + + fn tuple_variant(mut self, _len: usize, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + let seed = StructVariantSeed { visitor }; + self.map.next_value_seed(seed) + } + + fn struct_variant(mut self, _fields: &'static [&'static str], visitor: V) -> Result + where + V: de::Visitor<'de>, + { + let seed = StructVariantSeed { visitor }; + self.map.next_value_seed(seed) + } +} diff --git a/third_party/rust/serde_cbor/src/error.rs b/third_party/rust/serde_cbor/src/error.rs new file mode 100644 index 0000000000..b1a6a459e5 --- /dev/null +++ b/third_party/rust/serde_cbor/src/error.rs @@ -0,0 +1,318 @@ +//! When serializing or deserializing CBOR goes wrong. +use core::fmt; +use core::result; +use serde::de; +use serde::ser; +#[cfg(feature = "std")] +use std::error; +#[cfg(feature = "std")] +use std::io; + +/// This type represents all possible errors that can occur when serializing or deserializing CBOR +/// data. +pub struct Error(ErrorImpl); + +/// Alias for a `Result` with the error type `serde_cbor::Error`. +pub type Result = result::Result; + +/// Categorizes the cause of a `serde_cbor::Error`. +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +pub enum Category { + /// The error was caused by a failure to read or write bytes on an IO stream. + Io, + /// The error was caused by input that was not syntactically valid CBOR. + Syntax, + /// The error was caused by input data that was semantically incorrect. + Data, + /// The error was caused by prematurely reaching the end of the input data. + Eof, +} + +impl Error { + /// The byte offset at which the error occurred. + pub fn offset(&self) -> u64 { + self.0.offset + } + + pub(crate) fn syntax(code: ErrorCode, offset: u64) -> Error { + Error(ErrorImpl { code, offset }) + } + + #[cfg(feature = "std")] + pub(crate) fn io(error: io::Error) -> Error { + Error(ErrorImpl { + code: ErrorCode::Io(error), + offset: 0, + }) + } + + #[cfg(all(not(feature = "std"), feature = "unsealed_read_write"))] + /// Creates an error signalling that the underlying `Read` encountered an I/O error. + pub fn io() -> Error { + Error(ErrorImpl { + code: ErrorCode::Io, + offset: 0, + }) + } + + #[cfg(feature = "unsealed_read_write")] + /// Creates an error signalling that the scratch buffer was too small to fit the data. + pub fn scratch_too_small(offset: u64) -> Error { + Error(ErrorImpl { + code: ErrorCode::ScratchTooSmall, + offset, + }) + } + + #[cfg(not(feature = "unsealed_read_write"))] + pub(crate) fn scratch_too_small(offset: u64) -> Error { + Error(ErrorImpl { + code: ErrorCode::ScratchTooSmall, + offset, + }) + } + + #[cfg(feature = "unsealed_read_write")] + /// Creates an error with a custom message. + /// + /// **Note**: When the "std" feature is disabled, the message will be discarded. + pub fn message(_msg: T) -> Error { + #[cfg(not(feature = "std"))] + { + Error(ErrorImpl { + code: ErrorCode::Message, + offset: 0, + }) + } + #[cfg(feature = "std")] + { + Error(ErrorImpl { + code: ErrorCode::Message(_msg.to_string()), + offset: 0, + }) + } + } + + #[cfg(not(feature = "unsealed_read_write"))] + pub(crate) fn message(_msg: T) -> Error { + #[cfg(not(feature = "std"))] + { + Error(ErrorImpl { + code: ErrorCode::Message, + offset: 0, + }) + } + #[cfg(feature = "std")] + { + Error(ErrorImpl { + code: ErrorCode::Message(_msg.to_string()), + offset: 0, + }) + } + } + + #[cfg(feature = "unsealed_read_write")] + /// Creates an error signalling that the underlying read + /// encountered an end of input. + pub fn eof(offset: u64) -> Error { + Error(ErrorImpl { + code: ErrorCode::EofWhileParsingValue, + offset, + }) + } + + /// Categorizes the cause of this error. + pub fn classify(&self) -> Category { + match self.0.code { + #[cfg(feature = "std")] + ErrorCode::Message(_) => Category::Data, + #[cfg(not(feature = "std"))] + ErrorCode::Message => Category::Data, + #[cfg(feature = "std")] + ErrorCode::Io(_) => Category::Io, + #[cfg(not(feature = "std"))] + ErrorCode::Io => Category::Io, + ErrorCode::ScratchTooSmall => Category::Io, + ErrorCode::EofWhileParsingValue + | ErrorCode::EofWhileParsingArray + | ErrorCode::EofWhileParsingMap => Category::Eof, + ErrorCode::LengthOutOfRange + | ErrorCode::InvalidUtf8 + | ErrorCode::UnassignedCode + | ErrorCode::UnexpectedCode + | ErrorCode::TrailingData + | ErrorCode::ArrayTooShort + | ErrorCode::ArrayTooLong + | ErrorCode::RecursionLimitExceeded + | ErrorCode::WrongEnumFormat + | ErrorCode::WrongStructFormat => Category::Syntax, + } + } + + /// Returns true if this error was caused by a failure to read or write bytes on an IO stream. + pub fn is_io(&self) -> bool { + match self.classify() { + Category::Io => true, + _ => false, + } + } + + /// Returns true if this error was caused by input that was not syntactically valid CBOR. + pub fn is_syntax(&self) -> bool { + match self.classify() { + Category::Syntax => true, + _ => false, + } + } + + /// Returns true if this error was caused by data that was semantically incorrect. + pub fn is_data(&self) -> bool { + match self.classify() { + Category::Data => true, + _ => false, + } + } + + /// Returns true if this error was caused by prematurely reaching the end of the input data. + pub fn is_eof(&self) -> bool { + match self.classify() { + Category::Eof => true, + _ => false, + } + } + + /// Returns true if this error was caused by the scratch buffer being too small. + /// + /// Note this being `true` implies that `is_io()` is also `true`. + pub fn is_scratch_too_small(&self) -> bool { + match self.0.code { + ErrorCode::ScratchTooSmall => true, + _ => false, + } + } +} + +#[cfg(feature = "std")] +impl error::Error for Error { + fn source(&self) -> Option<&(dyn error::Error + 'static)> { + match self.0.code { + ErrorCode::Io(ref err) => Some(err), + _ => None, + } + } +} + +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + if self.0.offset == 0 { + fmt::Display::fmt(&self.0.code, f) + } else { + write!(f, "{} at offset {}", self.0.code, self.0.offset) + } + } +} + +impl fmt::Debug for Error { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt::Debug::fmt(&self.0, fmt) + } +} + +impl de::Error for Error { + fn custom(msg: T) -> Error { + Error::message(msg) + } + + fn invalid_type(unexp: de::Unexpected<'_>, exp: &dyn de::Expected) -> Error { + if let de::Unexpected::Unit = unexp { + Error::custom(format_args!("invalid type: null, expected {}", exp)) + } else { + Error::custom(format_args!("invalid type: {}, expected {}", unexp, exp)) + } + } +} + +impl ser::Error for Error { + fn custom(msg: T) -> Error { + Error::message(msg) + } +} + +#[cfg(feature = "std")] +impl From for Error { + fn from(e: io::Error) -> Error { + Error::io(e) + } +} + +#[cfg(not(feature = "std"))] +impl From for Error { + fn from(_: core::fmt::Error) -> Error { + Error(ErrorImpl { + code: ErrorCode::Message, + offset: 0, + }) + } +} + +#[derive(Debug)] +struct ErrorImpl { + code: ErrorCode, + offset: u64, +} + +#[derive(Debug)] +pub(crate) enum ErrorCode { + #[cfg(feature = "std")] + Message(String), + #[cfg(not(feature = "std"))] + Message, + #[cfg(feature = "std")] + Io(io::Error), + #[allow(unused)] + #[cfg(not(feature = "std"))] + Io, + ScratchTooSmall, + EofWhileParsingValue, + EofWhileParsingArray, + EofWhileParsingMap, + LengthOutOfRange, + InvalidUtf8, + UnassignedCode, + UnexpectedCode, + TrailingData, + ArrayTooShort, + ArrayTooLong, + RecursionLimitExceeded, + WrongEnumFormat, + WrongStructFormat, +} + +impl fmt::Display for ErrorCode { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + #[cfg(feature = "std")] + ErrorCode::Message(ref msg) => f.write_str(msg), + #[cfg(not(feature = "std"))] + ErrorCode::Message => f.write_str("Unknown error"), + #[cfg(feature = "std")] + ErrorCode::Io(ref err) => fmt::Display::fmt(err, f), + #[cfg(not(feature = "std"))] + ErrorCode::Io => f.write_str("Unknown I/O error"), + ErrorCode::ScratchTooSmall => f.write_str("Scratch buffer too small"), + ErrorCode::EofWhileParsingValue => f.write_str("EOF while parsing a value"), + ErrorCode::EofWhileParsingArray => f.write_str("EOF while parsing an array"), + ErrorCode::EofWhileParsingMap => f.write_str("EOF while parsing a map"), + ErrorCode::LengthOutOfRange => f.write_str("length out of range"), + ErrorCode::InvalidUtf8 => f.write_str("invalid UTF-8"), + ErrorCode::UnassignedCode => f.write_str("unassigned type"), + ErrorCode::UnexpectedCode => f.write_str("unexpected code"), + ErrorCode::TrailingData => f.write_str("trailing data"), + ErrorCode::ArrayTooShort => f.write_str("array too short"), + ErrorCode::ArrayTooLong => f.write_str("array too long"), + ErrorCode::RecursionLimitExceeded => f.write_str("recursion limit exceeded"), + ErrorCode::WrongEnumFormat => f.write_str("wrong enum format"), + ErrorCode::WrongStructFormat => f.write_str("wrong struct format"), + } + } +} diff --git a/third_party/rust/serde_cbor/src/lib.rs b/third_party/rust/serde_cbor/src/lib.rs new file mode 100644 index 0000000000..5566854153 --- /dev/null +++ b/third_party/rust/serde_cbor/src/lib.rs @@ -0,0 +1,369 @@ +//! CBOR and serialization. +//! +//! # Usage +//! +//! Serde CBOR supports Rust 1.40 and up. Add this to your `Cargo.toml`: +//! ```toml +//! [dependencies] +//! serde_cbor = "0.10" +//! ``` +//! +//! Storing and loading Rust types is easy and requires only +//! minimal modifications to the program code. +//! +//! ```rust +//! use serde_derive::{Deserialize, Serialize}; +//! use std::error::Error; +//! use std::fs::File; +//! +//! // Types annotated with `Serialize` can be stored as CBOR. +//! // To be able to load them again add `Deserialize`. +//! #[derive(Debug, Serialize, Deserialize)] +//! struct Mascot { +//! name: String, +//! species: String, +//! year_of_birth: u32, +//! } +//! +//! fn main() -> Result<(), Box> { +//! let ferris = Mascot { +//! name: "Ferris".to_owned(), +//! species: "crab".to_owned(), +//! year_of_birth: 2015, +//! }; +//! +//! let ferris_file = File::create("examples/ferris.cbor")?; +//! // Write Ferris to the given file. +//! // Instead of a file you can use any type that implements `io::Write` +//! // like a HTTP body, database connection etc. +//! serde_cbor::to_writer(ferris_file, &ferris)?; +//! +//! let tux_file = File::open("examples/tux.cbor")?; +//! // Load Tux from a file. +//! // Serde CBOR performs roundtrip serialization meaning that +//! // the data will not change in any way. +//! let tux: Mascot = serde_cbor::from_reader(tux_file)?; +//! +//! println!("{:?}", tux); +//! // prints: Mascot { name: "Tux", species: "penguin", year_of_birth: 1996 } +//! +//! Ok(()) +//! } +//! ``` +//! +//! There are a lot of options available to customize the format. +//! To operate on untyped CBOR values have a look at the `Value` type. +//! +//! # Type-based Serialization and Deserialization +//! Serde provides a mechanism for low boilerplate serialization & deserialization of values to and +//! from CBOR via the serialization API. To be able to serialize a piece of data, it must implement +//! the `serde::Serialize` trait. To be able to deserialize a piece of data, it must implement the +//! `serde::Deserialize` trait. Serde provides an annotation to automatically generate the +//! code for these traits: `#[derive(Serialize, Deserialize)]`. +//! +//! The CBOR API also provides an enum `serde_cbor::Value`. +//! +//! # Packed Encoding +//! When serializing structs or enums in CBOR the keys or enum variant names will be serialized +//! as string keys to a map. Especially in embedded environments this can increase the file +//! size too much. In packed encoding all struct keys, as well as any enum variant that has no data, +//! will be serialized as variable sized integers. The first 24 entries in any struct consume only a +//! single byte! Packed encoding uses serde's preferred [externally tagged enum +//! format](https://serde.rs/enum-representations.html) and therefore serializes enum variant names +//! as string keys when that variant contains data. So, in the packed encoding example, `FirstVariant` +//! encodes to a single byte, but encoding `SecondVariant` requires 16 bytes. +//! +//! To serialize a document in this format use `Serializer::new(writer).packed_format()` or +//! the shorthand `ser::to_vec_packed`. The deserialization works without any changes. +//! +//! If you would like to omit the enum variant encoding for all variants, including ones that +//! contain data, you can add `legacy_enums()` in addition to `packed_format()`, as can seen +//! in the Serialize using minimal encoding example. +//! +//! # Self describing documents +//! In some contexts different formats are used but there is no way to declare the format used +//! out of band. For this reason CBOR has a magic number that may be added before any document. +//! Self describing documents are created with `serializer.self_describe()`. +//! +//! # Examples +//! Read a CBOR value that is known to be a map of string keys to string values and print it. +//! +//! ```rust +//! use std::collections::BTreeMap; +//! use serde_cbor::from_slice; +//! +//! let slice = b"\xa5aaaAabaBacaCadaDaeaE"; +//! let value: BTreeMap = from_slice(slice).unwrap(); +//! println!("{:?}", value); // {"e": "E", "d": "D", "a": "A", "c": "C", "b": "B"} +//! ``` +//! +//! Read a general CBOR value with an unknown content. +//! +//! ```rust +//! use serde_cbor::from_slice; +//! use serde_cbor::value::Value; +//! +//! let slice = b"\x82\x01\xa1aaab"; +//! let value: Value = from_slice(slice).unwrap(); +//! println!("{:?}", value); // Array([U64(1), Object({String("a"): String("b")})]) +//! ``` +//! +//! Serialize an object. +//! +//! ```rust +//! use std::collections::BTreeMap; +//! use serde_cbor::to_vec; +//! +//! let mut programming_languages = BTreeMap::new(); +//! programming_languages.insert("rust", vec!["safe", "concurrent", "fast"]); +//! programming_languages.insert("python", vec!["powerful", "friendly", "open"]); +//! programming_languages.insert("js", vec!["lightweight", "interpreted", "object-oriented"]); +//! let encoded = to_vec(&programming_languages); +//! assert_eq!(encoded.unwrap().len(), 103); +//! ``` +//! +//! Deserializing data in the middle of a slice +//! ``` +//! # extern crate serde_cbor; +//! use serde_cbor::Deserializer; +//! +//! # fn main() { +//! let data: Vec = vec![ +//! 0x66, 0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72, 0x66, 0x66, 0x6f, 0x6f, 0x62, +//! 0x61, 0x72, +//! ]; +//! let mut deserializer = Deserializer::from_slice(&data); +//! let value: &str = serde::de::Deserialize::deserialize(&mut deserializer) +//! .unwrap(); +//! let rest = &data[deserializer.byte_offset()..]; +//! assert_eq!(value, "foobar"); +//! assert_eq!(rest, &[0x66, 0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72]); +//! # } +//! ``` +//! +//! Serialize using packed encoding +//! +//! ```rust +//! use serde_derive::{Deserialize, Serialize}; +//! use serde_cbor::ser::to_vec_packed; +//! use WithTwoVariants::*; +//! +//! #[derive(Debug, Serialize, Deserialize)] +//! enum WithTwoVariants { +//! FirstVariant, +//! SecondVariant(u8), +//! } +//! +//! let cbor = to_vec_packed(&FirstVariant).unwrap(); +//! assert_eq!(cbor.len(), 1); +//! +//! let cbor = to_vec_packed(&SecondVariant(0)).unwrap(); +//! assert_eq!(cbor.len(), 16); // Includes 13 bytes of "SecondVariant" +//! ``` +//! +//! Serialize using minimal encoding +//! +//! ```rust +//! use serde_derive::{Deserialize, Serialize}; +//! use serde_cbor::{Result, Serializer, ser::{self, IoWrite}}; +//! use WithTwoVariants::*; +//! +//! fn to_vec_minimal(value: &T) -> Result> +//! where +//! T: serde::Serialize, +//! { +//! let mut vec = Vec::new(); +//! value.serialize(&mut Serializer::new(&mut IoWrite::new(&mut vec)).packed_format().legacy_enums())?; +//! Ok(vec) +//! } +//! +//! #[derive(Debug, Serialize, Deserialize)] +//! enum WithTwoVariants { +//! FirstVariant, +//! SecondVariant(u8), +//! } +//! +//! let cbor = to_vec_minimal(&FirstVariant).unwrap(); +//! assert_eq!(cbor.len(), 1); +//! +//! let cbor = to_vec_minimal(&SecondVariant(0)).unwrap(); +//! assert_eq!(cbor.len(), 3); +//! ``` +//! +//! # `no-std` support +//! +//! Serde CBOR supports building in a `no_std` context, use the following lines +//! in your `Cargo.toml` dependencies: +//! ``` toml +//! [dependencies] +//! serde = { version = "1.0", default-features = false } +//! serde_cbor = { version = "0.10", default-features = false } +//! ``` +//! +//! Without the `std` feature the functions [from_reader], [from_slice], [to_vec], and [to_writer] +//! are not exported. To export [from_slice] and [to_vec] enable the `alloc` feature. The `alloc` +//! feature uses the [`alloc` library][alloc-lib] and requires at least version 1.36.0 of Rust. +//! +//! [alloc-lib]: https://doc.rust-lang.org/alloc/ +//! +//! *Note*: to use derive macros in serde you will need to declare `serde` +//! dependency like so: +//! ``` toml +//! serde = { version = "1.0", default-features = false, features = ["derive"] } +//! ``` +//! +//! Serialize an object with `no_std` and without `alloc`. +//! ``` rust +//! # #[macro_use] extern crate serde_derive; +//! # fn main() -> Result<(), serde_cbor::Error> { +//! use serde::Serialize; +//! use serde_cbor::Serializer; +//! use serde_cbor::ser::SliceWrite; +//! +//! #[derive(Serialize)] +//! struct User { +//! user_id: u32, +//! password_hash: [u8; 4], +//! } +//! +//! let mut buf = [0u8; 100]; +//! let writer = SliceWrite::new(&mut buf[..]); +//! let mut ser = Serializer::new(writer); +//! let user = User { +//! user_id: 42, +//! password_hash: [1, 2, 3, 4], +//! }; +//! user.serialize(&mut ser)?; +//! let writer = ser.into_inner(); +//! let size = writer.bytes_written(); +//! let expected = [ +//! 0xa2, 0x67, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x2a, 0x6d, +//! 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x5f, 0x68, 0x61, 0x73, +//! 0x68, 0x84, 0x1, 0x2, 0x3, 0x4 +//! ]; +//! assert_eq!(&buf[..size], expected); +//! # Ok(()) +//! # } +//! ``` +//! +//! Deserialize an object. +//! ``` rust +//! # #[macro_use] extern crate serde_derive; +//! # fn main() -> Result<(), serde_cbor::Error> { +//! #[derive(Debug, PartialEq, Deserialize)] +//! struct User { +//! user_id: u32, +//! password_hash: [u8; 4], +//! } +//! +//! let value = [ +//! 0xa2, 0x67, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x2a, 0x6d, +//! 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x5f, 0x68, 0x61, 0x73, +//! 0x68, 0x84, 0x1, 0x2, 0x3, 0x4 +//! ]; +//! +//! // from_slice_with_scratch will not alter input data, use it whenever you +//! // borrow from somewhere else. +//! // You will have to size your scratch according to the input data you +//! // expect. +//! use serde_cbor::de::from_slice_with_scratch; +//! let mut scratch = [0u8; 32]; +//! let user: User = from_slice_with_scratch(&value[..], &mut scratch)?; +//! assert_eq!(user, User { +//! user_id: 42, +//! password_hash: [1, 2, 3, 4], +//! }); +//! +//! let mut value = [ +//! 0xa2, 0x67, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x2a, 0x6d, +//! 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x5f, 0x68, 0x61, 0x73, +//! 0x68, 0x84, 0x1, 0x2, 0x3, 0x4 +//! ]; +//! +//! // from_mut_slice will move data around the input slice, you may only use it +//! // on data you may own or can modify. +//! use serde_cbor::de::from_mut_slice; +//! let user: User = from_mut_slice(&mut value[..])?; +//! assert_eq!(user, User { +//! user_id: 42, +//! password_hash: [1, 2, 3, 4], +//! }); +//! # Ok(()) +//! # } +//! ``` +//! +//! # Limitations +//! +//! While Serde CBOR strives to support all features of Serde and CBOR +//! there are a few limitations. +//! +//! * [Tags] are ignored during deserialization and can't be emitted during +//! serialization. This is because Serde has no concept of tagged +//! values. See: [#3] +//! * Unknown [simple values] cause an `UnassignedCode` error. +//! The simple values *False* and *True* are recognized and parsed as bool. +//! *Null* and *Undefined* are both deserialized as *unit*. +//! The *unit* type is serialized as *Null*. See: [#86] +//! * [128-bit integers] can't be directly encoded in CBOR. If you need them +//! store them as a byte string. See: [#77] +//! +//! [Tags]: https://tools.ietf.org/html/rfc7049#section-2.4.4 +//! [#3]: https://github.com/pyfisch/cbor/issues/3 +//! [simple values]: https://tools.ietf.org/html/rfc7049#section-3.5 +//! [#86]: https://github.com/pyfisch/cbor/issues/86 +//! [128-bit integers]: https://doc.rust-lang.org/std/primitive.u128.html +//! [#77]: https://github.com/pyfisch/cbor/issues/77 + +#![deny(missing_docs)] +#![cfg_attr(not(feature = "std"), no_std)] + +// When we are running tests in no_std mode we need to explicitly link std, because `cargo test` +// will not work without it. +#[cfg(all(not(feature = "std"), test))] +extern crate std; + +#[cfg(feature = "alloc")] +extern crate alloc; + +pub mod de; +pub mod error; +mod read; +pub mod ser; +pub mod tags; +mod write; + +#[cfg(feature = "std")] +pub mod value; + +// Re-export the [items recommended by serde](https://serde.rs/conventions.html). +#[doc(inline)] +pub use crate::de::{Deserializer, StreamDeserializer}; + +#[doc(inline)] +pub use crate::error::{Error, Result}; + +#[doc(inline)] +pub use crate::ser::Serializer; + +// Convenience functions for serialization and deserialization. +// These functions are only available in `std` mode. +#[cfg(feature = "std")] +#[doc(inline)] +pub use crate::de::from_reader; + +#[cfg(any(feature = "std", feature = "alloc"))] +#[doc(inline)] +pub use crate::de::from_slice; + +#[cfg(any(feature = "std", feature = "alloc"))] +#[doc(inline)] +pub use crate::ser::to_vec; + +#[cfg(feature = "std")] +#[doc(inline)] +pub use crate::ser::to_writer; + +// Re-export the value type like serde_json +#[cfg(feature = "std")] +#[doc(inline)] +pub use crate::value::Value; diff --git a/third_party/rust/serde_cbor/src/read.rs b/third_party/rust/serde_cbor/src/read.rs new file mode 100644 index 0000000000..1b53018df8 --- /dev/null +++ b/third_party/rust/serde_cbor/src/read.rs @@ -0,0 +1,637 @@ +#[cfg(feature = "alloc")] +use alloc::{vec, vec::Vec}; +#[cfg(feature = "std")] +use core::cmp; +use core::mem; + +#[cfg(feature = "std")] +use std::io::{self, Read as StdRead}; + +use crate::error::{Error, ErrorCode, Result}; + +#[cfg(not(feature = "unsealed_read_write"))] +/// Trait used by the deserializer for iterating over input. +/// +/// This trait is sealed by default, enabling the `unsealed_read_write` feature removes this bound +/// to allow objects outside of this crate to implement this trait. +pub trait Read<'de>: private::Sealed { + #[doc(hidden)] + /// Read n bytes from the input. + /// + /// Implementations that can are asked to return a slice with a Long lifetime that outlives the + /// decoder, but others (eg. ones that need to allocate the data into a temporary buffer) can + /// return it with a Short lifetime that just lives for the time of read's mutable borrow of + /// the reader. + /// + /// This may, as a side effect, clear the reader's scratch buffer (as the provided + /// implementation does). + + // A more appropriate lifetime setup for this (that would allow the Deserializer::convert_str + // to stay a function) would be something like `fn read<'a, 'r: 'a>(&'a mut 'r immut self, ...) -> ... + // EitherLifetime<'r, 'de>>`, which borrows self mutably for the duration of the function and + // downgrates that reference to an immutable one that outlives the result (protecting the + // scratch buffer from changes), but alas, that can't be expressed (yet?). + fn read<'a>(&'a mut self, n: usize) -> Result> { + self.clear_buffer(); + self.read_to_buffer(n)?; + + Ok(self.take_buffer()) + } + + #[doc(hidden)] + fn next(&mut self) -> Result>; + + #[doc(hidden)] + fn peek(&mut self) -> Result>; + + #[doc(hidden)] + fn clear_buffer(&mut self); + + #[doc(hidden)] + fn read_to_buffer(&mut self, n: usize) -> Result<()>; + + #[doc(hidden)] + fn take_buffer<'a>(&'a mut self) -> EitherLifetime<'a, 'de>; + + #[doc(hidden)] + fn read_into(&mut self, buf: &mut [u8]) -> Result<()>; + + #[doc(hidden)] + fn discard(&mut self); + + #[doc(hidden)] + fn offset(&self) -> u64; +} + +#[cfg(feature = "unsealed_read_write")] +/// Trait used by the deserializer for iterating over input. +pub trait Read<'de> { + /// Read n bytes from the input. + /// + /// Implementations that can are asked to return a slice with a Long lifetime that outlives the + /// decoder, but others (eg. ones that need to allocate the data into a temporary buffer) can + /// return it with a Short lifetime that just lives for the time of read's mutable borrow of + /// the reader. + /// + /// This may, as a side effect, clear the reader's scratch buffer (as the provided + /// implementation does). + + // A more appropriate lifetime setup for this (that would allow the Deserializer::convert_str + // to stay a function) would be something like `fn read<'a, 'r: 'a>(&'a mut 'r immut self, ...) -> ... + // EitherLifetime<'r, 'de>>`, which borrows self mutably for the duration of the function and + // downgrates that reference to an immutable one that outlives the result (protecting the + // scratch buffer from changes), but alas, that can't be expressed (yet?). + fn read<'a>(&'a mut self, n: usize) -> Result> { + self.clear_buffer(); + self.read_to_buffer(n)?; + + Ok(self.take_buffer()) + } + + /// Read the next byte from the input, if any. + fn next(&mut self) -> Result>; + + /// Peek at the next byte of the input, if any. This does not advance the reader, so the result + /// of this function will remain the same until a read or clear occurs. + fn peek(&mut self) -> Result>; + + /// Clear the underlying scratch buffer + fn clear_buffer(&mut self); + + /// Append n bytes from the reader to the reader's scratch buffer (without clearing it) + fn read_to_buffer(&mut self, n: usize) -> Result<()>; + + /// Read out everything accumulated in the reader's scratch buffer. This may, as a side effect, + /// clear it. + fn take_buffer<'a>(&'a mut self) -> EitherLifetime<'a, 'de>; + + /// Read from the input until `buf` is full or end of input is encountered. + fn read_into(&mut self, buf: &mut [u8]) -> Result<()>; + + /// Discard any data read by `peek`. + fn discard(&mut self); + + /// Returns the offset from the start of the reader. + fn offset(&self) -> u64; +} + +/// Represents a reader that can return its current position +pub trait Offset { + fn byte_offset(&self) -> usize; +} + +/// Represents a buffer with one of two lifetimes. +pub enum EitherLifetime<'short, 'long> { + /// The short lifetime + Short(&'short [u8]), + /// The long lifetime + Long(&'long [u8]), +} + +#[cfg(not(feature = "unsealed_read_write"))] +mod private { + pub trait Sealed {} +} + +/// CBOR input source that reads from a std::io input stream. +#[cfg(feature = "std")] +#[derive(Debug)] +pub struct IoRead +where + R: io::Read, +{ + reader: OffsetReader, + scratch: Vec, + ch: Option, +} + +#[cfg(feature = "std")] +impl IoRead +where + R: io::Read, +{ + /// Creates a new CBOR input source to read from a std::io input stream. + pub fn new(reader: R) -> IoRead { + IoRead { + reader: OffsetReader { reader, offset: 0 }, + scratch: vec![], + ch: None, + } + } + + #[inline] + fn next_inner(&mut self) -> Result> { + let mut buf = [0; 1]; + loop { + match self.reader.read(&mut buf) { + Ok(0) => return Ok(None), + Ok(_) => return Ok(Some(buf[0])), + Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {} + Err(e) => return Err(Error::io(e)), + } + } + } +} + +#[cfg(all(feature = "std", not(feature = "unsealed_read_write")))] +impl private::Sealed for IoRead where R: io::Read {} + +#[cfg(feature = "std")] +impl<'de, R> Read<'de> for IoRead +where + R: io::Read, +{ + #[inline] + fn next(&mut self) -> Result> { + match self.ch.take() { + Some(ch) => Ok(Some(ch)), + None => self.next_inner(), + } + } + + #[inline] + fn peek(&mut self) -> Result> { + match self.ch { + Some(ch) => Ok(Some(ch)), + None => { + self.ch = self.next_inner()?; + Ok(self.ch) + } + } + } + + fn read_to_buffer(&mut self, mut n: usize) -> Result<()> { + // defend against malicious input pretending to be huge strings by limiting growth + self.scratch.reserve(cmp::min(n, 16 * 1024)); + + if n == 0 { + return Ok(()); + } + + if let Some(ch) = self.ch.take() { + self.scratch.push(ch); + n -= 1; + } + + // n == 0 is OK here and needs no further special treatment + + let transfer_result = { + // Prepare for take() (which consumes its reader) by creating a reference adaptor + // that'll only live in this block + let reference = self.reader.by_ref(); + // Append the first n bytes of the reader to the scratch vector (or up to + // an error or EOF indicated by a shorter read) + let mut taken = reference.take(n as u64); + taken.read_to_end(&mut self.scratch) + }; + + match transfer_result { + Ok(r) if r == n => Ok(()), + Ok(_) => Err(Error::syntax( + ErrorCode::EofWhileParsingValue, + self.offset(), + )), + Err(e) => Err(Error::io(e)), + } + } + + fn clear_buffer(&mut self) { + self.scratch.clear(); + } + + fn take_buffer<'a>(&'a mut self) -> EitherLifetime<'a, 'de> { + EitherLifetime::Short(&self.scratch) + } + + fn read_into(&mut self, buf: &mut [u8]) -> Result<()> { + self.reader.read_exact(buf).map_err(|e| { + if e.kind() == io::ErrorKind::UnexpectedEof { + Error::syntax(ErrorCode::EofWhileParsingValue, self.offset()) + } else { + Error::io(e) + } + }) + } + + #[inline] + fn discard(&mut self) { + self.ch = None; + } + + fn offset(&self) -> u64 { + self.reader.offset + } +} + +#[cfg(feature = "std")] +impl Offset for IoRead +where + R: std::io::Read, +{ + fn byte_offset(&self) -> usize { + self.offset() as usize + } +} + +#[cfg(feature = "std")] +#[derive(Debug)] +struct OffsetReader { + reader: R, + offset: u64, +} + +#[cfg(feature = "std")] +impl io::Read for OffsetReader +where + R: io::Read, +{ + #[inline] + fn read(&mut self, buf: &mut [u8]) -> io::Result { + let r = self.reader.read(buf); + if let Ok(count) = r { + self.offset += count as u64; + } + r + } +} + +/// A CBOR input source that reads from a slice of bytes. +#[cfg(any(feature = "std", feature = "alloc"))] +#[derive(Debug)] +pub struct SliceRead<'a> { + slice: &'a [u8], + scratch: Vec, + index: usize, +} + +#[cfg(any(feature = "std", feature = "alloc"))] +impl<'a> SliceRead<'a> { + /// Creates a CBOR input source to read from a slice of bytes. + pub fn new(slice: &'a [u8]) -> SliceRead<'a> { + SliceRead { + slice, + scratch: vec![], + index: 0, + } + } + + fn end(&self, n: usize) -> Result { + match self.index.checked_add(n) { + Some(end) if end <= self.slice.len() => Ok(end), + _ => Err(Error::syntax( + ErrorCode::EofWhileParsingValue, + self.slice.len() as u64, + )), + } + } +} + +#[cfg(any(feature = "std", feature = "alloc"))] +impl<'a> Offset for SliceRead<'a> { + #[inline] + fn byte_offset(&self) -> usize { + self.index + } +} + +#[cfg(all( + any(feature = "std", feature = "alloc"), + not(feature = "unsealed_read_write") +))] +impl<'a> private::Sealed for SliceRead<'a> {} + +#[cfg(any(feature = "std", feature = "alloc"))] +impl<'a> Read<'a> for SliceRead<'a> { + #[inline] + fn next(&mut self) -> Result> { + Ok(if self.index < self.slice.len() { + let ch = self.slice[self.index]; + self.index += 1; + Some(ch) + } else { + None + }) + } + + #[inline] + fn peek(&mut self) -> Result> { + Ok(if self.index < self.slice.len() { + Some(self.slice[self.index]) + } else { + None + }) + } + + fn clear_buffer(&mut self) { + self.scratch.clear(); + } + + fn read_to_buffer(&mut self, n: usize) -> Result<()> { + let end = self.end(n)?; + let slice = &self.slice[self.index..end]; + self.scratch.extend_from_slice(slice); + self.index = end; + + Ok(()) + } + + #[inline] + fn read<'b>(&'b mut self, n: usize) -> Result> { + let end = self.end(n)?; + let slice = &self.slice[self.index..end]; + self.index = end; + Ok(EitherLifetime::Long(slice)) + } + + fn take_buffer<'b>(&'b mut self) -> EitherLifetime<'b, 'a> { + EitherLifetime::Short(&self.scratch) + } + + #[inline] + fn read_into(&mut self, buf: &mut [u8]) -> Result<()> { + let end = self.end(buf.len())?; + buf.copy_from_slice(&self.slice[self.index..end]); + self.index = end; + Ok(()) + } + + #[inline] + fn discard(&mut self) { + self.index += 1; + } + + fn offset(&self) -> u64 { + self.index as u64 + } +} + +/// A CBOR input source that reads from a slice of bytes using a fixed size scratch buffer. +/// +/// [`SliceRead`](struct.SliceRead.html) and [`MutSliceRead`](struct.MutSliceRead.html) are usually +/// preferred over this, as they can handle indefinite length items. +#[derive(Debug)] +pub struct SliceReadFixed<'a, 'b> { + slice: &'a [u8], + scratch: &'b mut [u8], + index: usize, + scratch_index: usize, +} + +impl<'a, 'b> SliceReadFixed<'a, 'b> { + /// Creates a CBOR input source to read from a slice of bytes, backed by a scratch buffer. + pub fn new(slice: &'a [u8], scratch: &'b mut [u8]) -> SliceReadFixed<'a, 'b> { + SliceReadFixed { + slice, + scratch, + index: 0, + scratch_index: 0, + } + } + + fn end(&self, n: usize) -> Result { + match self.index.checked_add(n) { + Some(end) if end <= self.slice.len() => Ok(end), + _ => Err(Error::syntax( + ErrorCode::EofWhileParsingValue, + self.slice.len() as u64, + )), + } + } + + fn scratch_end(&self, n: usize) -> Result { + match self.scratch_index.checked_add(n) { + Some(end) if end <= self.scratch.len() => Ok(end), + _ => Err(Error::scratch_too_small(self.index as u64)), + } + } +} + +#[cfg(not(feature = "unsealed_read_write"))] +impl<'a, 'b> private::Sealed for SliceReadFixed<'a, 'b> {} + +impl<'a, 'b> Read<'a> for SliceReadFixed<'a, 'b> { + #[inline] + fn next(&mut self) -> Result> { + Ok(if self.index < self.slice.len() { + let ch = self.slice[self.index]; + self.index += 1; + Some(ch) + } else { + None + }) + } + + #[inline] + fn peek(&mut self) -> Result> { + Ok(if self.index < self.slice.len() { + Some(self.slice[self.index]) + } else { + None + }) + } + + fn clear_buffer(&mut self) { + self.scratch_index = 0; + } + + fn read_to_buffer(&mut self, n: usize) -> Result<()> { + let end = self.end(n)?; + let scratch_end = self.scratch_end(n)?; + let slice = &self.slice[self.index..end]; + self.scratch[self.scratch_index..scratch_end].copy_from_slice(&slice); + self.index = end; + self.scratch_index = scratch_end; + + Ok(()) + } + + fn read<'c>(&'c mut self, n: usize) -> Result> { + let end = self.end(n)?; + let slice = &self.slice[self.index..end]; + self.index = end; + Ok(EitherLifetime::Long(slice)) + } + + fn take_buffer<'c>(&'c mut self) -> EitherLifetime<'c, 'a> { + EitherLifetime::Short(&self.scratch[0..self.scratch_index]) + } + + #[inline] + fn read_into(&mut self, buf: &mut [u8]) -> Result<()> { + let end = self.end(buf.len())?; + buf.copy_from_slice(&self.slice[self.index..end]); + self.index = end; + Ok(()) + } + + #[inline] + fn discard(&mut self) { + self.index += 1; + } + + fn offset(&self) -> u64 { + self.index as u64 + } +} + +#[cfg(any(feature = "std", feature = "alloc"))] +impl<'a, 'b> Offset for SliceReadFixed<'a, 'b> { + #[inline] + fn byte_offset(&self) -> usize { + self.index + } +} + +/// A CBOR input source that reads from a slice of bytes, and can move data around internally to +/// reassemble indefinite strings without the need of an allocated scratch buffer. +#[derive(Debug)] +pub struct MutSliceRead<'a> { + /// A complete view of the reader's data. It is promised that bytes before buffer_end are not + /// mutated any more. + slice: &'a mut [u8], + /// Read cursor position in slice + index: usize, + /// Number of bytes already discarded from the slice + before: usize, + /// End of the buffer area that contains all bytes read_into_buffer. This is always <= index. + buffer_end: usize, +} + +impl<'a> MutSliceRead<'a> { + /// Creates a CBOR input source to read from a slice of bytes. + pub fn new(slice: &'a mut [u8]) -> MutSliceRead<'a> { + MutSliceRead { + slice, + index: 0, + before: 0, + buffer_end: 0, + } + } + + fn end(&self, n: usize) -> Result { + match self.index.checked_add(n) { + Some(end) if end <= self.slice.len() => Ok(end), + _ => Err(Error::syntax( + ErrorCode::EofWhileParsingValue, + self.slice.len() as u64, + )), + } + } +} + +#[cfg(not(feature = "unsealed_read_write"))] +impl<'a> private::Sealed for MutSliceRead<'a> {} + +impl<'a> Read<'a> for MutSliceRead<'a> { + #[inline] + fn next(&mut self) -> Result> { + // This is duplicated from SliceRead, can that be eased? + Ok(if self.index < self.slice.len() { + let ch = self.slice[self.index]; + self.index += 1; + Some(ch) + } else { + None + }) + } + + #[inline] + fn peek(&mut self) -> Result> { + // This is duplicated from SliceRead, can that be eased? + Ok(if self.index < self.slice.len() { + Some(self.slice[self.index]) + } else { + None + }) + } + + fn clear_buffer(&mut self) { + self.slice = &mut mem::replace(&mut self.slice, &mut [])[self.index..]; + self.before += self.index; + self.index = 0; + self.buffer_end = 0; + } + + fn read_to_buffer(&mut self, n: usize) -> Result<()> { + let end = self.end(n)?; + debug_assert!( + self.buffer_end <= self.index, + "MutSliceRead invariant violated: scratch buffer exceeds index" + ); + self.slice[self.buffer_end..end].rotate_left(self.index - self.buffer_end); + self.buffer_end += n; + self.index = end; + + Ok(()) + } + + fn take_buffer<'b>(&'b mut self) -> EitherLifetime<'b, 'a> { + let (left, right) = mem::replace(&mut self.slice, &mut []).split_at_mut(self.index); + self.slice = right; + self.before += self.index; + self.index = 0; + + let left = &left[..self.buffer_end]; + self.buffer_end = 0; + + EitherLifetime::Long(left) + } + + #[inline] + fn read_into(&mut self, buf: &mut [u8]) -> Result<()> { + // This is duplicated from SliceRead, can that be eased? + let end = self.end(buf.len())?; + buf.copy_from_slice(&self.slice[self.index..end]); + self.index = end; + Ok(()) + } + + #[inline] + fn discard(&mut self) { + self.index += 1; + } + + fn offset(&self) -> u64 { + (self.before + self.index) as u64 + } +} diff --git a/third_party/rust/serde_cbor/src/ser.rs b/third_party/rust/serde_cbor/src/ser.rs new file mode 100644 index 0000000000..7016dc340a --- /dev/null +++ b/third_party/rust/serde_cbor/src/ser.rs @@ -0,0 +1,743 @@ +//! Serialize a Rust data structure to CBOR data. + +#[cfg(feature = "alloc")] +use alloc::vec::Vec; + +#[cfg(feature = "std")] +pub use crate::write::IoWrite; +pub use crate::write::{SliceWrite, Write}; + +use crate::error::{Error, Result}; +use half::f16; +use serde::ser::{self, Serialize}; +#[cfg(feature = "std")] +use std::io; + +use crate::tags::{get_tag, CBOR_NEWTYPE_NAME}; + +/// Serializes a value to a vector. +#[cfg(any(feature = "std", feature = "alloc"))] +pub fn to_vec(value: &T) -> Result> +where + T: ser::Serialize, +{ + let mut vec = Vec::new(); + value.serialize(&mut Serializer::new(&mut vec))?; + Ok(vec) +} + +/// Serializes a value to a vector in packed format. +#[cfg(feature = "std")] +pub fn to_vec_packed(value: &T) -> Result> +where + T: ser::Serialize, +{ + let mut vec = Vec::new(); + value.serialize(&mut Serializer::new(&mut IoWrite::new(&mut vec)).packed_format())?; + Ok(vec) +} + +/// Serializes a value to a writer. +#[cfg(feature = "std")] +pub fn to_writer(writer: W, value: &T) -> Result<()> +where + W: io::Write, + T: ser::Serialize, +{ + value.serialize(&mut Serializer::new(&mut IoWrite::new(writer))) +} + +/// A structure for serializing Rust values to CBOR. +#[derive(Debug)] +pub struct Serializer { + writer: W, + packed: bool, + enum_as_map: bool, +} + +impl Serializer +where + W: Write, +{ + /// Creates a new CBOR serializer. + /// + /// `to_vec` and `to_writer` should normally be used instead of this method. + #[inline] + pub fn new(writer: W) -> Self { + Serializer { + writer, + packed: false, + enum_as_map: true, + } + } + + /// Choose concise/packed format for serializer. + /// + /// In the packed format enum variant names and field names + /// are replaced with numeric indizes to conserve space. + pub fn packed_format(mut self) -> Self { + self.packed = true; + self + } + + /// Enable old enum format used by `serde_cbor` versions <= v0.9. + /// + /// The `legacy_enums` option determines how enums are encoded. + /// + /// This makes no difference when encoding and decoding enums using + /// this crate, but it shows up when decoding to a `Value` or decoding + /// in other languages. + /// + /// # Examples + /// + /// Given the following enum + /// + /// ```rust + /// enum Enum { + /// Unit, + /// NewType(i32), + /// Tuple(String, bool), + /// Struct{ x: i32, y: i32 }, + /// } + /// ``` + /// we will give the `Value` with the same encoding for each case using + /// JSON notation. + /// + /// ## Default encodings + /// + /// * `Enum::Unit` encodes as `"Unit"` + /// * `Enum::NewType(10)` encodes as `{"NewType": 10}` + /// * `Enum::Tuple("x", true)` encodes as `{"Tuple": ["x", true]}` + /// + /// ## Legacy encodings + /// + /// * `Enum::Unit` encodes as `"Unit"` + /// * `Enum::NewType(10)` encodes as `["NewType", 10]` + /// * `Enum::Tuple("x", true)` encodes as `["Tuple", "x", true]` + /// * `Enum::Struct{ x: 5, y: -5 }` encodes as `["Struct", {"x": 5, "y": -5}]` + pub fn legacy_enums(mut self) -> Self { + self.enum_as_map = false; + self + } + + /// Writes a CBOR self-describe tag to the stream. + /// + /// Tagging allows a decoder to distinguish different file formats based on their content + /// without further information. + #[inline] + pub fn self_describe(&mut self) -> Result<()> { + let mut buf = [6 << 5 | 25, 0, 0]; + (&mut buf[1..]).copy_from_slice(&55799u16.to_be_bytes()); + self.writer.write_all(&buf).map_err(|e| e.into()) + } + + /// Unwrap the `Writer` from the `Serializer`. + #[inline] + pub fn into_inner(self) -> W { + self.writer + } + + #[inline] + fn write_u8(&mut self, major: u8, value: u8) -> Result<()> { + if value <= 0x17 { + self.writer.write_all(&[major << 5 | value]) + } else { + let buf = [major << 5 | 24, value]; + self.writer.write_all(&buf) + } + .map_err(|e| e.into()) + } + + #[inline] + fn write_u16(&mut self, major: u8, value: u16) -> Result<()> { + if value <= u16::from(u8::max_value()) { + self.write_u8(major, value as u8) + } else { + let mut buf = [major << 5 | 25, 0, 0]; + (&mut buf[1..]).copy_from_slice(&value.to_be_bytes()); + self.writer.write_all(&buf).map_err(|e| e.into()) + } + } + + #[inline] + fn write_u32(&mut self, major: u8, value: u32) -> Result<()> { + if value <= u32::from(u16::max_value()) { + self.write_u16(major, value as u16) + } else { + let mut buf = [major << 5 | 26, 0, 0, 0, 0]; + (&mut buf[1..]).copy_from_slice(&value.to_be_bytes()); + self.writer.write_all(&buf).map_err(|e| e.into()) + } + } + + #[inline] + fn write_u64(&mut self, major: u8, value: u64) -> Result<()> { + if value <= u64::from(u32::max_value()) { + self.write_u32(major, value as u32) + } else { + let mut buf = [major << 5 | 27, 0, 0, 0, 0, 0, 0, 0, 0]; + (&mut buf[1..]).copy_from_slice(&value.to_be_bytes()); + self.writer.write_all(&buf).map_err(|e| e.into()) + } + } + + #[inline] + fn serialize_collection<'a>( + &'a mut self, + major: u8, + len: Option, + ) -> Result> { + let needs_eof = match len { + Some(len) => { + self.write_u64(major, len as u64)?; + false + } + None => { + self.writer + .write_all(&[major << 5 | 31]) + .map_err(|e| e.into())?; + true + } + }; + + Ok(CollectionSerializer { + ser: self, + needs_eof, + }) + } +} + +impl<'a, W> ser::Serializer for &'a mut Serializer +where + W: Write, +{ + type Ok = (); + type Error = Error; + + type SerializeSeq = CollectionSerializer<'a, W>; + type SerializeTuple = &'a mut Serializer; + type SerializeTupleStruct = &'a mut Serializer; + type SerializeTupleVariant = &'a mut Serializer; + type SerializeMap = CollectionSerializer<'a, W>; + type SerializeStruct = StructSerializer<'a, W>; + type SerializeStructVariant = StructSerializer<'a, W>; + + #[inline] + fn serialize_bool(self, value: bool) -> Result<()> { + let value = if value { 0xf5 } else { 0xf4 }; + self.writer.write_all(&[value]).map_err(|e| e.into()) + } + + #[inline] + fn serialize_i8(self, value: i8) -> Result<()> { + if value < 0 { + self.write_u8(1, -(value + 1) as u8) + } else { + self.write_u8(0, value as u8) + } + } + + #[inline] + fn serialize_i16(self, value: i16) -> Result<()> { + if value < 0 { + self.write_u16(1, -(value + 1) as u16) + } else { + self.write_u16(0, value as u16) + } + } + + #[inline] + fn serialize_i32(self, value: i32) -> Result<()> { + if value < 0 { + self.write_u32(1, -(value + 1) as u32) + } else { + self.write_u32(0, value as u32) + } + } + + #[inline] + fn serialize_i64(self, value: i64) -> Result<()> { + if value < 0 { + self.write_u64(1, -(value + 1) as u64) + } else { + self.write_u64(0, value as u64) + } + } + + #[inline] + fn serialize_i128(self, value: i128) -> Result<()> { + if value < 0 { + if -(value + 1) > i128::from(u64::max_value()) { + return Err(Error::message("The number can't be stored in CBOR")); + } + self.write_u64(1, -(value + 1) as u64) + } else { + if value > i128::from(u64::max_value()) { + return Err(Error::message("The number can't be stored in CBOR")); + } + self.write_u64(0, value as u64) + } + } + + #[inline] + fn serialize_u8(self, value: u8) -> Result<()> { + self.write_u8(0, value) + } + + #[inline] + fn serialize_u16(self, value: u16) -> Result<()> { + self.write_u16(0, value) + } + + #[inline] + fn serialize_u32(self, value: u32) -> Result<()> { + self.write_u32(0, value) + } + + #[inline] + fn serialize_u64(self, value: u64) -> Result<()> { + self.write_u64(0, value) + } + + #[inline] + fn serialize_u128(self, value: u128) -> Result<()> { + if value > u128::from(u64::max_value()) { + return Err(Error::message("The number can't be stored in CBOR")); + } + self.write_u64(0, value as u64) + } + + #[inline] + #[allow(clippy::float_cmp)] + fn serialize_f32(self, value: f32) -> Result<()> { + if value.is_infinite() { + if value.is_sign_positive() { + self.writer.write_all(&[0xf9, 0x7c, 0x00]) + } else { + self.writer.write_all(&[0xf9, 0xfc, 0x00]) + } + } else if value.is_nan() { + self.writer.write_all(&[0xf9, 0x7e, 0x00]) + } else if f32::from(f16::from_f32(value)) == value { + let mut buf = [0xf9, 0, 0]; + (&mut buf[1..]).copy_from_slice(&f16::from_f32(value).to_bits().to_be_bytes()); + self.writer.write_all(&buf) + } else { + let mut buf = [0xfa, 0, 0, 0, 0]; + (&mut buf[1..]).copy_from_slice(&value.to_bits().to_be_bytes()); + self.writer.write_all(&buf) + } + .map_err(|e| e.into()) + } + + #[inline] + #[allow(clippy::float_cmp)] + fn serialize_f64(self, value: f64) -> Result<()> { + if !value.is_finite() || f64::from(value as f32) == value { + self.serialize_f32(value as f32) + } else { + let mut buf = [0xfb, 0, 0, 0, 0, 0, 0, 0, 0]; + (&mut buf[1..]).copy_from_slice(&value.to_bits().to_be_bytes()); + self.writer.write_all(&buf).map_err(|e| e.into()) + } + } + + #[inline] + fn serialize_char(self, value: char) -> Result<()> { + // A char encoded as UTF-8 takes 4 bytes at most. + let mut buf = [0; 4]; + self.serialize_str(value.encode_utf8(&mut buf)) + } + + #[inline] + fn serialize_str(self, value: &str) -> Result<()> { + self.write_u64(3, value.len() as u64)?; + self.writer + .write_all(value.as_bytes()) + .map_err(|e| e.into()) + } + + #[inline] + fn serialize_bytes(self, value: &[u8]) -> Result<()> { + self.write_u64(2, value.len() as u64)?; + self.writer.write_all(value).map_err(|e| e.into()) + } + + #[inline] + fn serialize_unit(self) -> Result<()> { + self.serialize_none() + } + + #[inline] + fn serialize_some(self, value: &T) -> Result<()> + where + T: ?Sized + ser::Serialize, + { + value.serialize(self) + } + + #[inline] + fn serialize_none(self) -> Result<()> { + self.writer.write_all(&[0xf6]).map_err(|e| e.into()) + } + + #[inline] + fn serialize_unit_struct(self, _name: &'static str) -> Result<()> { + self.serialize_unit() + } + + #[inline] + fn serialize_unit_variant( + self, + _name: &'static str, + variant_index: u32, + variant: &'static str, + ) -> Result<()> { + if self.packed { + self.serialize_u32(variant_index) + } else { + self.serialize_str(variant) + } + } + + #[inline] + fn serialize_newtype_struct(self, name: &'static str, value: &T) -> Result<()> + where + T: ?Sized + ser::Serialize, + { + if name == CBOR_NEWTYPE_NAME { + for tag in get_tag().into_iter() { + self.write_u64(6, tag)?; + } + } + value.serialize(self) + } + + #[inline] + fn serialize_newtype_variant( + self, + name: &'static str, + variant_index: u32, + variant: &'static str, + value: &T, + ) -> Result<()> + where + T: ?Sized + ser::Serialize, + { + if self.enum_as_map { + self.write_u64(5, 1u64)?; + variant.serialize(&mut *self)?; + } else { + self.writer.write_all(&[4 << 5 | 2]).map_err(|e| e.into())?; + self.serialize_unit_variant(name, variant_index, variant)?; + } + value.serialize(self) + } + + #[inline] + fn serialize_seq(self, len: Option) -> Result> { + self.serialize_collection(4, len) + } + + #[inline] + fn serialize_tuple(self, len: usize) -> Result<&'a mut Serializer> { + self.write_u64(4, len as u64)?; + Ok(self) + } + + #[inline] + fn serialize_tuple_struct( + self, + _name: &'static str, + len: usize, + ) -> Result<&'a mut Serializer> { + self.serialize_tuple(len) + } + + #[inline] + fn serialize_tuple_variant( + self, + name: &'static str, + variant_index: u32, + variant: &'static str, + len: usize, + ) -> Result<&'a mut Serializer> { + if self.enum_as_map { + self.write_u64(5, 1u64)?; + variant.serialize(&mut *self)?; + self.serialize_tuple(len) + } else { + self.write_u64(4, (len + 1) as u64)?; + self.serialize_unit_variant(name, variant_index, variant)?; + Ok(self) + } + } + + #[inline] + fn serialize_map(self, len: Option) -> Result> { + self.serialize_collection(5, len) + } + + #[cfg(not(feature = "std"))] + fn collect_str(self, value: &T) -> Result<()> + where + T: core::fmt::Display, + { + use crate::write::FmtWrite; + use core::fmt::Write; + + let mut w = FmtWrite::new(&mut self.writer); + write!(w, "{}", value)?; + Ok(()) + } + + #[inline] + fn serialize_struct(self, _name: &'static str, len: usize) -> Result> { + self.write_u64(5, len as u64)?; + Ok(StructSerializer { ser: self, idx: 0 }) + } + + #[inline] + fn serialize_struct_variant( + self, + name: &'static str, + variant_index: u32, + variant: &'static str, + len: usize, + ) -> Result> { + if self.enum_as_map { + self.write_u64(5, 1u64)?; + } else { + self.writer.write_all(&[4 << 5 | 2]).map_err(|e| e.into())?; + } + self.serialize_unit_variant(name, variant_index, variant)?; + self.serialize_struct(name, len) + } + + #[inline] + fn is_human_readable(&self) -> bool { + false + } +} + +impl<'a, W> ser::SerializeTuple for &'a mut Serializer +where + W: Write, +{ + type Ok = (); + type Error = Error; + + #[inline] + fn serialize_element(&mut self, value: &T) -> Result<()> + where + T: ?Sized + ser::Serialize, + { + value.serialize(&mut **self) + } + + #[inline] + fn end(self) -> Result<()> { + Ok(()) + } +} + +impl<'a, W> ser::SerializeTupleStruct for &'a mut Serializer +where + W: Write, +{ + type Ok = (); + type Error = Error; + + #[inline] + fn serialize_field(&mut self, value: &T) -> Result<()> + where + T: ?Sized + ser::Serialize, + { + value.serialize(&mut **self) + } + + #[inline] + fn end(self) -> Result<()> { + Ok(()) + } +} + +impl<'a, W> ser::SerializeTupleVariant for &'a mut Serializer +where + W: Write, +{ + type Ok = (); + type Error = Error; + + #[inline] + fn serialize_field(&mut self, value: &T) -> Result<()> + where + T: ?Sized + ser::Serialize, + { + value.serialize(&mut **self) + } + + #[inline] + fn end(self) -> Result<()> { + Ok(()) + } +} + +#[doc(hidden)] +pub struct StructSerializer<'a, W> { + ser: &'a mut Serializer, + idx: u32, +} + +impl<'a, W> StructSerializer<'a, W> +where + W: Write, +{ + #[inline] + fn serialize_field_inner(&mut self, key: &'static str, value: &T) -> Result<()> + where + T: ?Sized + ser::Serialize, + { + if self.ser.packed { + self.idx.serialize(&mut *self.ser)?; + } else { + key.serialize(&mut *self.ser)?; + } + value.serialize(&mut *self.ser)?; + self.idx += 1; + Ok(()) + } + + #[inline] + fn skip_field_inner(&mut self, _: &'static str) -> Result<()> { + self.idx += 1; + Ok(()) + } + + #[inline] + fn end_inner(self) -> Result<()> { + Ok(()) + } +} + +impl<'a, W> ser::SerializeStruct for StructSerializer<'a, W> +where + W: Write, +{ + type Ok = (); + type Error = Error; + + #[inline] + fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<()> + where + T: ?Sized + ser::Serialize, + { + self.serialize_field_inner(key, value) + } + + #[inline] + fn skip_field(&mut self, key: &'static str) -> Result<()> { + self.skip_field_inner(key) + } + + #[inline] + fn end(self) -> Result<()> { + self.end_inner() + } +} + +impl<'a, W> ser::SerializeStructVariant for StructSerializer<'a, W> +where + W: Write, +{ + type Ok = (); + type Error = Error; + + #[inline] + fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<()> + where + T: ?Sized + ser::Serialize, + { + self.serialize_field_inner(key, value) + } + + #[inline] + fn skip_field(&mut self, key: &'static str) -> Result<()> { + self.skip_field_inner(key) + } + + #[inline] + fn end(self) -> Result<()> { + self.end_inner() + } +} + +#[doc(hidden)] +pub struct CollectionSerializer<'a, W> { + ser: &'a mut Serializer, + needs_eof: bool, +} + +impl<'a, W> CollectionSerializer<'a, W> +where + W: Write, +{ + #[inline] + fn end_inner(self) -> Result<()> { + if self.needs_eof { + self.ser.writer.write_all(&[0xff]).map_err(|e| e.into()) + } else { + Ok(()) + } + } +} + +impl<'a, W> ser::SerializeSeq for CollectionSerializer<'a, W> +where + W: Write, +{ + type Ok = (); + type Error = Error; + + #[inline] + fn serialize_element(&mut self, value: &T) -> Result<()> + where + T: ?Sized + ser::Serialize, + { + value.serialize(&mut *self.ser) + } + + #[inline] + fn end(self) -> Result<()> { + self.end_inner() + } +} + +impl<'a, W> ser::SerializeMap for CollectionSerializer<'a, W> +where + W: Write, +{ + type Ok = (); + type Error = Error; + + #[inline] + fn serialize_key(&mut self, key: &T) -> Result<()> + where + T: ?Sized + ser::Serialize, + { + key.serialize(&mut *self.ser) + } + + #[inline] + fn serialize_value(&mut self, value: &T) -> Result<()> + where + T: ?Sized + ser::Serialize, + { + value.serialize(&mut *self.ser) + } + + #[inline] + fn end(self) -> Result<()> { + self.end_inner() + } +} diff --git a/third_party/rust/serde_cbor/src/tags.rs b/third_party/rust/serde_cbor/src/tags.rs new file mode 100644 index 0000000000..8adccb8ea8 --- /dev/null +++ b/third_party/rust/serde_cbor/src/tags.rs @@ -0,0 +1,220 @@ +//! Support for cbor tags +use core::fmt; +use core::marker::PhantomData; +use serde::de::{ + Deserialize, Deserializer, EnumAccess, IntoDeserializer, MapAccess, SeqAccess, Visitor, +}; +use serde::forward_to_deserialize_any; +use serde::ser::{Serialize, Serializer}; + +/// signals that a newtype is from a CBOR tag +pub(crate) const CBOR_NEWTYPE_NAME: &str = "\0cbor_tag"; + +/// A value that is optionally tagged with a cbor tag +/// +/// this only serves as an intermediate helper for tag serialization or deserialization +pub struct Tagged { + /// cbor tag + pub tag: Option, + /// value + pub value: T, +} + +impl Tagged { + /// Create a new tagged value + pub fn new(tag: Option, value: T) -> Self { + Self { tag, value } + } +} + +impl Serialize for Tagged { + fn serialize(&self, s: S) -> Result { + set_tag(self.tag); + let r = s.serialize_newtype_struct(CBOR_NEWTYPE_NAME, &self.value); + set_tag(None); + r + } +} + +fn untagged(value: T) -> Tagged { + Tagged::new(None, value) +} + +macro_rules! delegate { + ($name: ident, $type: ty) => { + fn $name(self, v: $type) -> Result { + T::deserialize(v.into_deserializer()).map(untagged) + } + }; +} + +struct EnumDeserializer(A); + +impl<'de, A> Deserializer<'de> for EnumDeserializer +where + A: EnumAccess<'de>, +{ + type Error = A::Error; + + fn deserialize_any>(self, visitor: V) -> Result { + visitor.visit_enum(self.0) + } + + forward_to_deserialize_any! { + bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string + bytes byte_buf option unit unit_struct newtype_struct seq tuple + tuple_struct map struct enum identifier ignored_any + } +} + +struct NoneDeserializer(PhantomData); + +impl<'de, E> Deserializer<'de> for NoneDeserializer +where + E: serde::de::Error, +{ + type Error = E; + + fn deserialize_any>(self, visitor: V) -> Result { + visitor.visit_none() + } + + forward_to_deserialize_any! { + bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string + bytes byte_buf option unit unit_struct newtype_struct seq tuple + tuple_struct map struct enum identifier ignored_any + } +} + +struct BytesDeserializer<'a, E>(&'a [u8], PhantomData); + +impl<'de, 'a, E> Deserializer<'de> for BytesDeserializer<'a, E> +where + E: serde::de::Error, +{ + type Error = E; + + fn deserialize_any>(self, visitor: V) -> Result { + visitor.visit_bytes(self.0) + } + + forward_to_deserialize_any! { + bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string + bytes byte_buf option unit unit_struct newtype_struct seq tuple + tuple_struct map struct enum identifier ignored_any + } +} + +/// A visitor that intercepts *just* visit_newtype_struct and passes through everything else. +struct MaybeTaggedVisitor(PhantomData); + +impl<'de, T: Deserialize<'de>> Visitor<'de> for MaybeTaggedVisitor { + type Value = Tagged; + + fn expecting(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt.write_str("a cbor tag newtype") + } + + delegate!(visit_bool, bool); + + delegate!(visit_i8, i8); + delegate!(visit_i16, i16); + delegate!(visit_i32, i32); + delegate!(visit_i64, i64); + + delegate!(visit_u8, u8); + delegate!(visit_u16, u16); + delegate!(visit_u32, u32); + delegate!(visit_u64, u64); + + delegate!(visit_f32, f32); + delegate!(visit_f64, f64); + + delegate!(visit_char, char); + delegate!(visit_str, &str); + delegate!(visit_borrowed_str, &'de str); + + #[cfg(feature = "std")] + delegate!(visit_byte_buf, Vec); + + #[cfg(feature = "std")] + delegate!(visit_string, String); + + fn visit_bytes(self, value: &[u8]) -> Result { + T::deserialize(BytesDeserializer(value, PhantomData)).map(untagged) + } + + fn visit_borrowed_bytes(self, value: &'de [u8]) -> Result { + T::deserialize(serde::de::value::BorrowedBytesDeserializer::new(value)).map(untagged) + } + + fn visit_unit(self) -> Result { + T::deserialize(().into_deserializer()).map(untagged) + } + + fn visit_none(self) -> Result { + T::deserialize(NoneDeserializer(PhantomData)).map(untagged) + } + + fn visit_some>(self, deserializer: D) -> Result { + T::deserialize(deserializer).map(untagged) + } + + fn visit_seq>(self, seq: A) -> Result { + T::deserialize(serde::de::value::SeqAccessDeserializer::new(seq)).map(untagged) + } + + fn visit_map>(self, map: V) -> Result { + T::deserialize(serde::de::value::MapAccessDeserializer::new(map)).map(untagged) + } + + fn visit_enum>(self, data: A) -> Result { + T::deserialize(EnumDeserializer(data)).map(untagged) + } + + fn visit_newtype_struct>( + self, + deserializer: D, + ) -> Result { + let t = get_tag(); + T::deserialize(deserializer).map(|v| Tagged::new(t, v)) + } +} + +impl<'de, T: serde::de::Deserialize<'de>> serde::de::Deserialize<'de> for Tagged { + fn deserialize>(deserializer: D) -> Result { + deserializer.deserialize_any(MaybeTaggedVisitor::(PhantomData)) + } +} + +/// function to get the current cbor tag +/// +/// The only place where it makes sense to call this function is within visit_newtype_struct of a serde visitor. +/// This is a low level API. In most cases it is preferable to use Tagged +pub fn current_cbor_tag() -> Option { + get_tag() +} + +#[cfg(feature = "tags")] +pub(crate) fn set_tag(value: Option) { + CBOR_TAG.with(|f| *f.borrow_mut() = value); +} + +#[cfg(feature = "tags")] +pub(crate) fn get_tag() -> Option { + CBOR_TAG.with(|f| *f.borrow()) +} + +#[cfg(not(feature = "tags"))] +pub(crate) fn set_tag(_value: Option) {} + +#[cfg(not(feature = "tags"))] +pub(crate) fn get_tag() -> Option { + None +} + +#[cfg(feature = "tags")] +use std::cell::RefCell; + +#[cfg(feature = "tags")] +thread_local!(static CBOR_TAG: RefCell> = RefCell::new(None)); diff --git a/third_party/rust/serde_cbor/src/value/de.rs b/third_party/rust/serde_cbor/src/value/de.rs new file mode 100644 index 0000000000..f5bdbb7467 --- /dev/null +++ b/third_party/rust/serde_cbor/src/value/de.rs @@ -0,0 +1,166 @@ +use std::collections::BTreeMap; +use std::fmt; + +use crate::value::Value; +use serde::de; + +impl<'de> de::Deserialize<'de> for Value { + #[inline] + fn deserialize(deserializer: D) -> Result + where + D: de::Deserializer<'de>, + { + struct ValueVisitor; + + impl<'de> de::Visitor<'de> for ValueVisitor { + type Value = Value; + + fn expecting(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt.write_str("any valid CBOR value") + } + + #[inline] + fn visit_str(self, value: &str) -> Result + where + E: de::Error, + { + self.visit_string(String::from(value)) + } + + #[inline] + fn visit_string(self, value: String) -> Result + where + E: de::Error, + { + Ok(Value::Text(value)) + } + #[inline] + fn visit_bytes(self, v: &[u8]) -> Result + where + E: de::Error, + { + self.visit_byte_buf(v.to_owned()) + } + + #[inline] + fn visit_byte_buf(self, v: Vec) -> Result + where + E: de::Error, + { + Ok(Value::Bytes(v)) + } + + #[inline] + fn visit_u64(self, v: u64) -> Result + where + E: de::Error, + { + Ok(Value::Integer(v.into())) + } + + #[inline] + fn visit_i64(self, v: i64) -> Result + where + E: de::Error, + { + Ok(Value::Integer(v.into())) + } + + #[inline] + fn visit_i128(self, v: i128) -> Result + where + E: de::Error, + { + Ok(Value::Integer(v)) + } + + #[inline] + fn visit_bool(self, v: bool) -> Result + where + E: de::Error, + { + Ok(Value::Bool(v)) + } + + #[inline] + fn visit_none(self) -> Result + where + E: de::Error, + { + self.visit_unit() + } + + #[inline] + fn visit_unit(self) -> Result + where + E: de::Error, + { + Ok(Value::Null) + } + + #[inline] + fn visit_seq(self, mut visitor: V) -> Result + where + V: de::SeqAccess<'de>, + { + let mut vec = Vec::new(); + + while let Some(elem) = visitor.next_element()? { + vec.push(elem); + } + + Ok(Value::Array(vec)) + } + + #[inline] + fn visit_map(self, mut visitor: V) -> Result + where + V: de::MapAccess<'de>, + { + let mut values = BTreeMap::new(); + + while let Some((key, value)) = visitor.next_entry()? { + values.insert(key, value); + } + + Ok(Value::Map(values)) + } + + #[inline] + fn visit_f64(self, v: f64) -> Result + where + E: de::Error, + { + Ok(Value::Float(v)) + } + + fn visit_newtype_struct(self, deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let tag = crate::tags::get_tag(); + let inner = deserializer.deserialize_any(self); + match tag { + Some(tag) => inner.map(|v| Value::Tag(tag, Box::new(v))), + None => inner, + } + } + } + + deserializer.deserialize_any(ValueVisitor) + } +} + +/// Convert a `serde_cbor::Value` into a type `T` +#[allow(clippy::needless_pass_by_value)] +pub fn from_value(value: Value) -> Result +where + T: de::DeserializeOwned, +{ + // TODO implement in a way that doesn't require + // roundtrip through buffer (i.e. by implementing + // `serde::de::Deserializer` for `Value` and then doing + // `T::deserialize(value)`). + let buf = crate::to_vec(&value)?; + crate::from_slice(buf.as_slice()) +} diff --git a/third_party/rust/serde_cbor/src/value/mod.rs b/third_party/rust/serde_cbor/src/value/mod.rs new file mode 100644 index 0000000000..7bd2255314 --- /dev/null +++ b/third_party/rust/serde_cbor/src/value/mod.rs @@ -0,0 +1,156 @@ +//! CBOR values, keys and serialization routines. + +mod de; +mod ser; + +use std::cmp::{Ord, Ordering, PartialOrd}; +use std::collections::BTreeMap; + +#[doc(inline)] +pub use self::de::from_value; +#[doc(inline)] +pub use self::ser::to_value; + +/// The `Value` enum, a loosely typed way of representing any valid CBOR value. +/// +/// Maps are sorted according to the canonical ordering +/// described in [RFC 7049 bis]. +/// Therefore values are unambiguously serialized +/// to a canonical form of CBOR from the same RFC. +/// +/// [RFC 7049 bis]: https://tools.ietf.org/html/draft-ietf-cbor-7049bis-04#section-2 +#[derive(Clone, Debug)] +pub enum Value { + /// Represents the absence of a value or the value undefined. + Null, + /// Represents a boolean value. + Bool(bool), + /// Integer CBOR numbers. + /// + /// The biggest value that can be represented is 2^64 - 1. + /// While the smallest value is -2^64. + /// Values outside this range can't be serialized + /// and will cause an error. + Integer(i128), + /// Represents a floating point value. + Float(f64), + /// Represents a byte string. + Bytes(Vec), + /// Represents an UTF-8 encoded string. + Text(String), + /// Represents an array of values. + Array(Vec), + /// Represents a map. + /// + /// Maps are also called tables, dictionaries, hashes, or objects (in JSON). + /// While any value can be used as a CBOR key + /// it is better to use only one type of key in a map + /// to avoid ambiguity. + /// If floating point values are used as keys they are compared bit-by-bit for equality. + /// If arrays or maps are used as keys the comparisons + /// to establish canonical order may be slow and therefore insertion + /// and retrieval of values will be slow too. + Map(BTreeMap), + /// Represents a tagged value + Tag(u64, Box), + // The hidden variant allows the enum to be extended + // with variants for tags and simple values. + #[doc(hidden)] + __Hidden, +} + +impl PartialEq for Value { + fn eq(&self, other: &Value) -> bool { + self.cmp(other) == Ordering::Equal + } +} + +impl Eq for Value {} + +impl PartialOrd for Value { + fn partial_cmp(&self, other: &Value) -> Option { + Some(self.cmp(other)) + } +} + +impl Ord for Value { + fn cmp(&self, other: &Value) -> Ordering { + // Determine the canonical order of two values: + // 1. Smaller major type sorts first. + // 2. Shorter sequence sorts first. + // 3. Compare integers by magnitude. + // 4. Compare byte and text sequences lexically. + // 5. Compare the serializations of both types. (expensive) + use self::Value::*; + if self.major_type() != other.major_type() { + return self.major_type().cmp(&other.major_type()); + } + match (self, other) { + (Integer(a), Integer(b)) => a.abs().cmp(&b.abs()), + (Bytes(a), Bytes(b)) if a.len() != b.len() => a.len().cmp(&b.len()), + (Text(a), Text(b)) if a.len() != b.len() => a.len().cmp(&b.len()), + (Array(a), Array(b)) if a.len() != b.len() => a.len().cmp(&b.len()), + (Map(a), Map(b)) if a.len() != b.len() => a.len().cmp(&b.len()), + (Bytes(a), Bytes(b)) => a.cmp(b), + (Text(a), Text(b)) => a.cmp(b), + (a, b) => { + let a = crate::to_vec(a).expect("self is serializable"); + let b = crate::to_vec(b).expect("other is serializable"); + a.cmp(&b) + } + } + } +} + +macro_rules! impl_from { + ($variant:path, $for_type:ty) => { + impl From<$for_type> for Value { + fn from(v: $for_type) -> Value { + $variant(v.into()) + } + } + }; +} + +impl_from!(Value::Bool, bool); +impl_from!(Value::Integer, i8); +impl_from!(Value::Integer, i16); +impl_from!(Value::Integer, i32); +impl_from!(Value::Integer, i64); +// i128 omitted because not all numbers fit in CBOR serialization +impl_from!(Value::Integer, u8); +impl_from!(Value::Integer, u16); +impl_from!(Value::Integer, u32); +impl_from!(Value::Integer, u64); +// u128 omitted because not all numbers fit in CBOR serialization +impl_from!(Value::Float, f32); +impl_from!(Value::Float, f64); +impl_from!(Value::Bytes, Vec); +impl_from!(Value::Text, String); +// TODO: figure out if these impls should be more generic or removed. +impl_from!(Value::Array, Vec); +impl_from!(Value::Map, BTreeMap); + +impl Value { + fn major_type(&self) -> u8 { + use self::Value::*; + match self { + Null => 7, + Bool(_) => 7, + Integer(v) => { + if *v >= 0 { + 0 + } else { + 1 + } + } + Tag(_, _) => 6, + Float(_) => 7, + Bytes(_) => 2, + Text(_) => 3, + Array(_) => 4, + Map(_) => 5, + __Hidden => unreachable!(), + } + } +} diff --git a/third_party/rust/serde_cbor/src/value/ser.rs b/third_party/rust/serde_cbor/src/value/ser.rs new file mode 100644 index 0000000000..347aae9601 --- /dev/null +++ b/third_party/rust/serde_cbor/src/value/ser.rs @@ -0,0 +1,443 @@ +// Copyright 2017 Serde Developers +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::collections::BTreeMap; + +use crate::error::Error; +use serde::{self, Serialize}; + +use crate::tags::Tagged; +use crate::value::Value; + +impl serde::Serialize for Value { + #[inline] + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + match *self { + Value::Integer(v) => serializer.serialize_i128(v), + Value::Bytes(ref v) => serializer.serialize_bytes(&v), + Value::Text(ref v) => serializer.serialize_str(&v), + Value::Array(ref v) => v.serialize(serializer), + Value::Map(ref v) => v.serialize(serializer), + Value::Tag(tag, ref v) => Tagged::new(Some(tag), v).serialize(serializer), + Value::Float(v) => serializer.serialize_f64(v), + Value::Bool(v) => serializer.serialize_bool(v), + Value::Null => serializer.serialize_unit(), + Value::__Hidden => unreachable!(), + } + } +} + +struct Serializer; + +impl serde::Serializer for Serializer { + type Ok = Value; + type Error = Error; + + type SerializeSeq = SerializeVec; + type SerializeTuple = SerializeVec; + type SerializeTupleStruct = SerializeVec; + type SerializeTupleVariant = SerializeTupleVariant; + type SerializeMap = SerializeMap; + type SerializeStruct = SerializeMap; + type SerializeStructVariant = SerializeStructVariant; + + #[inline] + fn serialize_bool(self, value: bool) -> Result { + Ok(Value::Bool(value)) + } + + #[inline] + fn serialize_i8(self, value: i8) -> Result { + self.serialize_i64(i64::from(value)) + } + + #[inline] + fn serialize_i16(self, value: i16) -> Result { + self.serialize_i64(i64::from(value)) + } + + #[inline] + fn serialize_i32(self, value: i32) -> Result { + self.serialize_i64(i64::from(value)) + } + + #[inline] + fn serialize_i64(self, value: i64) -> Result { + self.serialize_i128(i128::from(value)) + } + + fn serialize_i128(self, value: i128) -> Result { + Ok(Value::Integer(value)) + } + + #[inline] + fn serialize_u8(self, value: u8) -> Result { + self.serialize_u64(u64::from(value)) + } + + #[inline] + fn serialize_u16(self, value: u16) -> Result { + self.serialize_u64(u64::from(value)) + } + + #[inline] + fn serialize_u32(self, value: u32) -> Result { + self.serialize_u64(u64::from(value)) + } + + #[inline] + fn serialize_u64(self, value: u64) -> Result { + Ok(Value::Integer(value.into())) + } + + #[inline] + fn serialize_f32(self, value: f32) -> Result { + self.serialize_f64(f64::from(value)) + } + + #[inline] + fn serialize_f64(self, value: f64) -> Result { + Ok(Value::Float(value)) + } + + #[inline] + fn serialize_char(self, value: char) -> Result { + let mut s = String::new(); + s.push(value); + self.serialize_str(&s) + } + + #[inline] + fn serialize_str(self, value: &str) -> Result { + Ok(Value::Text(value.to_owned())) + } + + fn serialize_bytes(self, value: &[u8]) -> Result { + Ok(Value::Bytes(value.to_vec())) + } + + #[inline] + fn serialize_unit(self) -> Result { + Ok(Value::Null) + } + + #[inline] + fn serialize_unit_struct(self, _name: &'static str) -> Result { + self.serialize_unit() + } + + #[inline] + fn serialize_unit_variant( + self, + _name: &'static str, + _variant_index: u32, + variant: &'static str, + ) -> Result { + self.serialize_str(variant) + } + + #[inline] + fn serialize_newtype_struct( + self, + _name: &'static str, + value: &T, + ) -> Result + where + T: Serialize, + { + value.serialize(self) + } + + fn serialize_newtype_variant( + self, + _name: &'static str, + _variant_index: u32, + variant: &'static str, + value: &T, + ) -> Result + where + T: Serialize, + { + let mut values = BTreeMap::new(); + values.insert(Value::from(variant.to_owned()), to_value(&value)?); + Ok(Value::Map(values)) + } + + #[inline] + fn serialize_none(self) -> Result { + self.serialize_unit() + } + + #[inline] + fn serialize_some(self, value: &T) -> Result + where + T: Serialize, + { + value.serialize(self) + } + + fn serialize_seq(self, len: Option) -> Result { + Ok(SerializeVec { + vec: Vec::with_capacity(len.unwrap_or(0)), + }) + } + + fn serialize_tuple(self, len: usize) -> Result { + self.serialize_seq(Some(len)) + } + + fn serialize_tuple_struct( + self, + _name: &'static str, + len: usize, + ) -> Result { + self.serialize_tuple(len) + } + + fn serialize_tuple_variant( + self, + _name: &'static str, + _variant_index: u32, + variant: &'static str, + len: usize, + ) -> Result { + Ok(SerializeTupleVariant { + name: String::from(variant), + vec: Vec::with_capacity(len), + }) + } + + fn serialize_map(self, _len: Option) -> Result { + Ok(SerializeMap { + map: BTreeMap::new(), + next_key: None, + }) + } + + fn serialize_struct( + self, + _name: &'static str, + len: usize, + ) -> Result { + self.serialize_map(Some(len)) + } + + fn serialize_struct_variant( + self, + _name: &'static str, + _variant_index: u32, + variant: &'static str, + _len: usize, + ) -> Result { + Ok(SerializeStructVariant { + name: String::from(variant), + map: BTreeMap::new(), + }) + } + + #[inline] + fn is_human_readable(&self) -> bool { + false + } +} + +pub struct SerializeVec { + vec: Vec, +} + +pub struct SerializeTupleVariant { + name: String, + vec: Vec, +} + +pub struct SerializeMap { + map: BTreeMap, + next_key: Option, +} + +pub struct SerializeStructVariant { + name: String, + map: BTreeMap, +} + +impl serde::ser::SerializeSeq for SerializeVec { + type Ok = Value; + type Error = Error; + + fn serialize_element(&mut self, value: &T) -> Result<(), Error> + where + T: Serialize, + { + self.vec.push(to_value(&value)?); + Ok(()) + } + + fn end(self) -> Result { + Ok(Value::Array(self.vec)) + } +} + +impl serde::ser::SerializeTuple for SerializeVec { + type Ok = Value; + type Error = Error; + + fn serialize_element(&mut self, value: &T) -> Result<(), Error> + where + T: Serialize, + { + serde::ser::SerializeSeq::serialize_element(self, value) + } + + fn end(self) -> Result { + serde::ser::SerializeSeq::end(self) + } +} + +impl serde::ser::SerializeTupleStruct for SerializeVec { + type Ok = Value; + type Error = Error; + + fn serialize_field(&mut self, value: &T) -> Result<(), Error> + where + T: Serialize, + { + serde::ser::SerializeSeq::serialize_element(self, value) + } + + fn end(self) -> Result { + serde::ser::SerializeSeq::end(self) + } +} + +impl serde::ser::SerializeTupleVariant for SerializeTupleVariant { + type Ok = Value; + type Error = Error; + + fn serialize_field(&mut self, value: &T) -> Result<(), Error> + where + T: Serialize, + { + self.vec.push(to_value(&value)?); + Ok(()) + } + + fn end(self) -> Result { + let mut object = BTreeMap::new(); + + object.insert(Value::from(self.name), Value::Array(self.vec)); + + Ok(Value::Map(object)) + } +} + +impl serde::ser::SerializeMap for SerializeMap { + type Ok = Value; + type Error = Error; + + fn serialize_key(&mut self, key: &T) -> Result<(), Error> + where + T: Serialize, + { + self.next_key = Some(to_value(&key)?); + Ok(()) + } + + fn serialize_value(&mut self, value: &T) -> Result<(), Error> + where + T: Serialize, + { + let key = self.next_key.take(); + // Panic because this indicates a bug in the program rather than an + // expected failure. + let key = key.expect("serialize_value called before serialize_key"); + self.map.insert(key, to_value(&value)?); + Ok(()) + } + + fn end(self) -> Result { + Ok(Value::Map(self.map)) + } +} + +impl serde::ser::SerializeStruct for SerializeMap { + type Ok = Value; + type Error = Error; + + fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<(), Error> + where + T: Serialize, + { + serde::ser::SerializeMap::serialize_key(self, key)?; + serde::ser::SerializeMap::serialize_value(self, value) + } + + fn end(self) -> Result { + serde::ser::SerializeMap::end(self) + } +} + +impl serde::ser::SerializeStructVariant for SerializeStructVariant { + type Ok = Value; + type Error = Error; + + fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<(), Error> + where + T: Serialize, + { + self.map + .insert(Value::from(String::from(key)), to_value(&value)?); + Ok(()) + } + + fn end(self) -> Result { + let mut object = BTreeMap::new(); + + object.insert(Value::from(self.name), Value::Map(self.map)); + + Ok(Value::Map(object)) + } +} + +/// Convert a `T` into `serde_cbor::Value` which is an enum that can represent +/// any valid CBOR data. +/// +/// ```rust +/// extern crate serde; +/// +/// #[macro_use] +/// extern crate serde_derive; +/// extern crate serde_cbor; +/// +/// use std::error::Error; +/// +/// #[derive(Serialize)] +/// struct User { +/// fingerprint: String, +/// location: String, +/// } +/// +/// fn main() { +/// let u = User { +/// fingerprint: "0xF9BA143B95FF6D82".to_owned(), +/// location: "Menlo Park, CA".to_owned(), +/// }; +/// +/// let v = serde_cbor::value::to_value(u).unwrap(); +/// } +/// ``` +#[allow(clippy::needless_pass_by_value)] +// Taking by value is more friendly to iterator adapters, option and result +pub fn to_value(value: T) -> Result +where + T: Serialize, +{ + value.serialize(Serializer) +} diff --git a/third_party/rust/serde_cbor/src/write.rs b/third_party/rust/serde_cbor/src/write.rs new file mode 100644 index 0000000000..94c326ef96 --- /dev/null +++ b/third_party/rust/serde_cbor/src/write.rs @@ -0,0 +1,175 @@ +#[cfg(feature = "alloc")] +use alloc::vec::Vec; +#[cfg(not(feature = "std"))] +use core::fmt; +#[cfg(feature = "std")] +use std::io; + +use crate::error; + +#[cfg(not(feature = "unsealed_read_write"))] +/// A sink for serialized CBOR. +/// +/// This trait is similar to the [`Write`]() trait in the standard library, +/// but has a smaller and more general API. +/// +/// Any object implementing `std::io::Write` +/// can be wrapped in an [`IoWrite`](../write/struct.IoWrite.html) that implements +/// this trait for the underlying object. +pub trait Write: private::Sealed { + /// The type of error returned when a write operation fails. + #[doc(hidden)] + type Error: Into; + + /// Attempts to write an entire buffer into this write. + #[doc(hidden)] + fn write_all(&mut self, buf: &[u8]) -> Result<(), Self::Error>; +} + +#[cfg(feature = "unsealed_read_write")] +/// A sink for serialized CBOR. +/// +/// This trait is similar to the [`Write`]() trait in the standard library, +/// but has a smaller and more general API. +/// +/// Any object implementing `std::io::Write` +/// can be wrapped in an [`IoWrite`](../write/struct.IoWrite.html) that implements +/// this trait for the underlying object. +/// +/// This trait is sealed by default, enabling the `unsealed_read_write` feature removes this bound +/// to allow objects outside of this crate to implement this trait. +pub trait Write { + /// The type of error returned when a write operation fails. + type Error: Into; + + /// Attempts to write an entire buffer into this write. + fn write_all(&mut self, buf: &[u8]) -> Result<(), Self::Error>; +} + +#[cfg(not(feature = "unsealed_read_write"))] +mod private { + pub trait Sealed {} +} + +impl Write for &mut W +where + W: Write, +{ + type Error = W::Error; + + fn write_all(&mut self, buf: &[u8]) -> Result<(), Self::Error> { + (*self).write_all(buf) + } +} + +#[cfg(not(feature = "unsealed_read_write"))] +impl private::Sealed for &mut W where W: Write {} + +#[cfg(feature = "std")] +/// A wrapper for types that implement +/// [`std::io::Write`](https://doc.rust-lang.org/std/io/trait.Write.html) to implement the local +/// [`Write`](trait.Write.html) trait. +#[derive(Debug)] +pub struct IoWrite(W); + +#[cfg(feature = "std")] +impl IoWrite { + /// Wraps an `io::Write` writer to make it compatible with [`Write`](trait.Write.html) + pub fn new(w: W) -> IoWrite { + IoWrite(w) + } +} + +#[cfg(feature = "std")] +impl Write for IoWrite { + type Error = io::Error; + + fn write_all(&mut self, buf: &[u8]) -> Result<(), Self::Error> { + self.0.write_all(buf) + } +} + +#[cfg(all(feature = "std", not(feature = "unsealed_read_write")))] +impl private::Sealed for IoWrite where W: io::Write {} + +#[cfg(any(feature = "std", feature = "alloc"))] +impl Write for Vec { + type Error = error::Error; + + fn write_all(&mut self, buf: &[u8]) -> Result<(), Self::Error> { + self.extend_from_slice(buf); + Ok(()) + } +} + +#[cfg(all( + any(feature = "std", feature = "alloc"), + not(feature = "unsealed_read_write") +))] +impl private::Sealed for Vec {} + +#[cfg(not(feature = "std"))] +#[derive(Debug)] +pub struct FmtWrite<'a, W: Write>(&'a mut W); + +#[cfg(not(feature = "std"))] +impl<'a, W: Write> FmtWrite<'a, W> { + /// Wraps an `fmt::Write` writer to make it compatible with [`Write`](trait.Write.html) + pub fn new(w: &'a mut W) -> FmtWrite<'a, W> { + FmtWrite(w) + } +} + +#[cfg(not(feature = "std"))] +impl<'a, W: Write> fmt::Write for FmtWrite<'a, W> { + fn write_str(&mut self, s: &str) -> fmt::Result { + self.0.write_all(s.as_bytes()).map_err(|_| fmt::Error) + } +} + +#[cfg(all(not(feature = "std"), not(feature = "unsealed_read_write")))] +impl<'a, W> private::Sealed for FmtWrite<'a, W> where W: Write {} + +/// Implements [`Write`](trait.Write.html) for mutable byte slices (`&mut [u8]`). +/// +/// Returns an error if the value to serialize is too large to fit in the slice. +#[derive(Debug)] +pub struct SliceWrite<'a> { + slice: &'a mut [u8], + index: usize, +} + +impl<'a> SliceWrite<'a> { + /// Wraps a mutable slice so it can be used as a `Write`. + pub fn new(slice: &'a mut [u8]) -> SliceWrite<'a> { + SliceWrite { slice, index: 0 } + } + + /// Returns the number of bytes written to the underlying slice. + pub fn bytes_written(&self) -> usize { + self.index + } + + /// Returns the underlying slice. + pub fn into_inner(self) -> &'a mut [u8] { + self.slice + } +} + +impl<'a> Write for SliceWrite<'a> { + type Error = error::Error; + + fn write_all(&mut self, buf: &[u8]) -> Result<(), Self::Error> { + if self.slice.len() - self.index < buf.len() { + // This buffer will not fit in our slice + return Err(error::Error::scratch_too_small(self.index as u64)); + } + let end = self.index + buf.len(); + self.slice[self.index..end].copy_from_slice(buf); + self.index = end; + Ok(()) + } +} + +#[cfg(not(feature = "unsealed_read_write"))] +impl<'a> private::Sealed for SliceWrite<'a> {} -- cgit v1.2.3