diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 14:29:10 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 14:29:10 +0000 |
commit | 2aa4a82499d4becd2284cdb482213d541b8804dd (patch) | |
tree | b80bf8bf13c3766139fbacc530efd0dd9d54394c /third_party/rust/serde_bytes/src | |
parent | Initial commit. (diff) | |
download | firefox-2aa4a82499d4becd2284cdb482213d541b8804dd.tar.xz firefox-2aa4a82499d4becd2284cdb482213d541b8804dd.zip |
Adding upstream version 86.0.1.upstream/86.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/serde_bytes/src')
-rw-r--r-- | third_party/rust/serde_bytes/src/bytebuf.rs | 252 | ||||
-rw-r--r-- | third_party/rust/serde_bytes/src/bytes.rs | 195 | ||||
-rw-r--r-- | third_party/rust/serde_bytes/src/de.rs | 105 | ||||
-rw-r--r-- | third_party/rust/serde_bytes/src/lib.rs | 108 | ||||
-rw-r--r-- | third_party/rust/serde_bytes/src/ser.rs | 107 |
5 files changed, 767 insertions, 0 deletions
diff --git a/third_party/rust/serde_bytes/src/bytebuf.rs b/third_party/rust/serde_bytes/src/bytebuf.rs new file mode 100644 index 0000000000..c3f158aaa3 --- /dev/null +++ b/third_party/rust/serde_bytes/src/bytebuf.rs @@ -0,0 +1,252 @@ +use core::borrow::{Borrow, BorrowMut}; +use core::cmp::{self, Ordering}; +use core::fmt::{self, Debug}; +use core::hash::{Hash, Hasher}; +use core::ops::{Deref, DerefMut}; + +#[cfg(feature = "alloc")] +use alloc::boxed::Box; +#[cfg(feature = "alloc")] +use alloc::string::String; +#[cfg(feature = "alloc")] +use alloc::vec::Vec; + +use serde::de::{Deserialize, Deserializer, Error, SeqAccess, Visitor}; +use serde::ser::{Serialize, Serializer}; + +use crate::Bytes; + +/// Wrapper around `Vec<u8>` to serialize and deserialize efficiently. +/// +/// ``` +/// use std::collections::HashMap; +/// use std::io; +/// +/// use serde_bytes::ByteBuf; +/// +/// fn deserialize_bytebufs() -> bincode::Result<()> { +/// let example_data = [ +/// 2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 116, +/// 119, 111, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 111, 110, 101]; +/// +/// let map: HashMap<u32, ByteBuf> = bincode::deserialize(&example_data[..])?; +/// +/// println!("{:?}", map); +/// +/// Ok(()) +/// } +/// # +/// # fn main() { +/// # deserialize_bytebufs().unwrap(); +/// # } +/// ``` +#[derive(Clone, Default, Eq, Ord)] +pub struct ByteBuf { + bytes: Vec<u8>, +} + +impl ByteBuf { + /// Construct a new, empty `ByteBuf`. + pub fn new() -> Self { + ByteBuf::from(Vec::new()) + } + + /// Construct a new, empty `ByteBuf` with the specified capacity. + pub fn with_capacity(cap: usize) -> Self { + ByteBuf::from(Vec::with_capacity(cap)) + } + + /// Wrap existing bytes in a `ByteBuf`. + pub fn from<T: Into<Vec<u8>>>(bytes: T) -> Self { + ByteBuf { + bytes: bytes.into(), + } + } + + /// Unwrap the vector of byte underlying this `ByteBuf`. + pub fn into_vec(self) -> Vec<u8> { + self.bytes + } + + #[allow(missing_docs)] + pub fn into_boxed_bytes(self) -> Box<Bytes> { + self.bytes.into_boxed_slice().into() + } + + // This would hit "cannot move out of borrowed content" if invoked through + // the Deref impl; make it just work. + #[doc(hidden)] + pub fn into_boxed_slice(self) -> Box<[u8]> { + self.bytes.into_boxed_slice() + } + + #[doc(hidden)] + pub fn into_iter(self) -> <Vec<u8> as IntoIterator>::IntoIter { + self.bytes.into_iter() + } +} + +impl Debug for ByteBuf { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + Debug::fmt(&self.bytes, f) + } +} + +impl AsRef<[u8]> for ByteBuf { + fn as_ref(&self) -> &[u8] { + &self.bytes + } +} + +impl AsMut<[u8]> for ByteBuf { + fn as_mut(&mut self) -> &mut [u8] { + &mut self.bytes + } +} + +impl Deref for ByteBuf { + type Target = Vec<u8>; + + fn deref(&self) -> &Self::Target { + &self.bytes + } +} + +impl DerefMut for ByteBuf { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.bytes + } +} + +impl Borrow<Bytes> for ByteBuf { + fn borrow(&self) -> &Bytes { + Bytes::new(&self.bytes) + } +} + +impl BorrowMut<Bytes> for ByteBuf { + fn borrow_mut(&mut self) -> &mut Bytes { + unsafe { &mut *(&mut self.bytes as &mut [u8] as *mut [u8] as *mut Bytes) } + } +} + +impl<Rhs> PartialEq<Rhs> for ByteBuf +where + Rhs: ?Sized + AsRef<[u8]>, +{ + fn eq(&self, other: &Rhs) -> bool { + self.as_ref().eq(other.as_ref()) + } +} + +impl<Rhs> PartialOrd<Rhs> for ByteBuf +where + Rhs: ?Sized + AsRef<[u8]>, +{ + fn partial_cmp(&self, other: &Rhs) -> Option<Ordering> { + self.as_ref().partial_cmp(other.as_ref()) + } +} + +impl Hash for ByteBuf { + fn hash<H: Hasher>(&self, state: &mut H) { + self.bytes.hash(state); + } +} + +impl IntoIterator for ByteBuf { + type Item = u8; + type IntoIter = <Vec<u8> as IntoIterator>::IntoIter; + + fn into_iter(self) -> Self::IntoIter { + self.bytes.into_iter() + } +} + +impl<'a> IntoIterator for &'a ByteBuf { + type Item = &'a u8; + type IntoIter = <&'a [u8] as IntoIterator>::IntoIter; + + fn into_iter(self) -> Self::IntoIter { + self.bytes.iter() + } +} + +impl<'a> IntoIterator for &'a mut ByteBuf { + type Item = &'a mut u8; + type IntoIter = <&'a mut [u8] as IntoIterator>::IntoIter; + + fn into_iter(self) -> Self::IntoIter { + self.bytes.iter_mut() + } +} + +impl Serialize for ByteBuf { + fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> + where + S: Serializer, + { + serializer.serialize_bytes(&self.bytes) + } +} + +struct ByteBufVisitor; + +impl<'de> Visitor<'de> for ByteBufVisitor { + type Value = ByteBuf; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("byte array") + } + + fn visit_seq<V>(self, mut visitor: V) -> Result<ByteBuf, V::Error> + where + V: SeqAccess<'de>, + { + let len = cmp::min(visitor.size_hint().unwrap_or(0), 4096); + let mut values = Vec::with_capacity(len); + + while let Some(value) = visitor.next_element()? { + values.push(value); + } + + Ok(ByteBuf::from(values)) + } + + fn visit_bytes<E>(self, v: &[u8]) -> Result<ByteBuf, E> + where + E: Error, + { + Ok(ByteBuf::from(v)) + } + + fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<ByteBuf, E> + where + E: Error, + { + Ok(ByteBuf::from(v)) + } + + fn visit_str<E>(self, v: &str) -> Result<ByteBuf, E> + where + E: Error, + { + Ok(ByteBuf::from(v)) + } + + fn visit_string<E>(self, v: String) -> Result<ByteBuf, E> + where + E: Error, + { + Ok(ByteBuf::from(v)) + } +} + +impl<'de> Deserialize<'de> for ByteBuf { + fn deserialize<D>(deserializer: D) -> Result<ByteBuf, D::Error> + where + D: Deserializer<'de>, + { + deserializer.deserialize_byte_buf(ByteBufVisitor) + } +} diff --git a/third_party/rust/serde_bytes/src/bytes.rs b/third_party/rust/serde_bytes/src/bytes.rs new file mode 100644 index 0000000000..8fafbf5d9d --- /dev/null +++ b/third_party/rust/serde_bytes/src/bytes.rs @@ -0,0 +1,195 @@ +use core::cmp::Ordering; +use core::fmt::{self, Debug}; +use core::hash::{Hash, Hasher}; +use core::ops::{Deref, DerefMut}; + +#[cfg(feature = "alloc")] +use alloc::borrow::ToOwned; + +#[cfg(feature = "alloc")] +use alloc::boxed::Box; + +#[cfg(any(feature = "std", feature = "alloc"))] +use crate::ByteBuf; + +use serde::de::{Deserialize, Deserializer, Error, Visitor}; +use serde::ser::{Serialize, Serializer}; + +/// Wrapper around `&[u8]` to serialize and deserialize efficiently. +/// +/// ``` +/// use std::collections::HashMap; +/// use std::io; +/// +/// use serde_bytes::Bytes; +/// +/// fn print_encoded_cache() -> bincode::Result<()> { +/// let mut cache = HashMap::new(); +/// cache.insert(3, Bytes::new(b"three")); +/// cache.insert(2, Bytes::new(b"two")); +/// cache.insert(1, Bytes::new(b"one")); +/// +/// bincode::serialize_into(&mut io::stdout(), &cache) +/// } +/// # +/// # fn main() { +/// # print_encoded_cache().unwrap(); +/// # } +/// ``` +#[derive(Eq, Ord)] +#[repr(C)] +pub struct Bytes { + bytes: [u8], +} + +impl Bytes { + /// Wrap an existing `&[u8]`. + pub fn new(bytes: &[u8]) -> &Self { + unsafe { &*(bytes as *const [u8] as *const Bytes) } + } +} + +impl Debug for Bytes { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + Debug::fmt(&self.bytes, f) + } +} + +impl AsRef<[u8]> for Bytes { + fn as_ref(&self) -> &[u8] { + &self.bytes + } +} + +impl AsMut<[u8]> for Bytes { + fn as_mut(&mut self) -> &mut [u8] { + &mut self.bytes + } +} + +impl Deref for Bytes { + type Target = [u8]; + + fn deref(&self) -> &Self::Target { + &self.bytes + } +} + +impl DerefMut for Bytes { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.bytes + } +} + +#[cfg(any(feature = "std", feature = "alloc"))] +impl ToOwned for Bytes { + type Owned = ByteBuf; + + fn to_owned(&self) -> Self::Owned { + ByteBuf::from(&self.bytes) + } +} + +#[cfg(any(feature = "std", feature = "alloc"))] +impl From<Box<[u8]>> for Box<Bytes> { + fn from(bytes: Box<[u8]>) -> Self { + unsafe { Box::from_raw(Box::into_raw(bytes) as *mut Bytes) } + } +} + +impl<'a> Default for &'a Bytes { + fn default() -> Self { + Bytes::new(&[]) + } +} + +#[cfg(any(feature = "std", feature = "alloc"))] +impl Default for Box<Bytes> { + fn default() -> Self { + ByteBuf::new().into_boxed_bytes() + } +} + +impl<Rhs> PartialEq<Rhs> for Bytes +where + Rhs: ?Sized + AsRef<[u8]>, +{ + fn eq(&self, other: &Rhs) -> bool { + self.as_ref().eq(other.as_ref()) + } +} + +impl<Rhs> PartialOrd<Rhs> for Bytes +where + Rhs: ?Sized + AsRef<[u8]>, +{ + fn partial_cmp(&self, other: &Rhs) -> Option<Ordering> { + self.as_ref().partial_cmp(other.as_ref()) + } +} + +impl Hash for Bytes { + fn hash<H: Hasher>(&self, state: &mut H) { + self.bytes.hash(state); + } +} + +impl<'a> IntoIterator for &'a Bytes { + type Item = &'a u8; + type IntoIter = <&'a [u8] as IntoIterator>::IntoIter; + + fn into_iter(self) -> Self::IntoIter { + self.bytes.iter() + } +} + +impl<'a> IntoIterator for &'a mut Bytes { + type Item = &'a mut u8; + type IntoIter = <&'a mut [u8] as IntoIterator>::IntoIter; + + fn into_iter(self) -> Self::IntoIter { + self.bytes.iter_mut() + } +} + +impl Serialize for Bytes { + fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> + where + S: Serializer, + { + serializer.serialize_bytes(&self.bytes) + } +} + +struct BytesVisitor; + +impl<'de> Visitor<'de> for BytesVisitor { + type Value = &'de Bytes; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("a borrowed byte array") + } + + fn visit_borrowed_bytes<E>(self, v: &'de [u8]) -> Result<Self::Value, E> + where + E: Error, + { + Ok(Bytes::new(v)) + } + + fn visit_borrowed_str<E>(self, v: &'de str) -> Result<Self::Value, E> + where + E: Error, + { + Ok(Bytes::new(v.as_bytes())) + } +} + +impl<'a, 'de: 'a> Deserialize<'de> for &'a Bytes { + fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> + where + D: Deserializer<'de>, + { + deserializer.deserialize_bytes(BytesVisitor) + } +} diff --git a/third_party/rust/serde_bytes/src/de.rs b/third_party/rust/serde_bytes/src/de.rs new file mode 100644 index 0000000000..862368aaee --- /dev/null +++ b/third_party/rust/serde_bytes/src/de.rs @@ -0,0 +1,105 @@ +use crate::Bytes; +use serde::Deserializer; + +#[cfg(any(feature = "std", feature = "alloc"))] +use crate::ByteBuf; + +#[cfg(feature = "alloc")] +use alloc::borrow::Cow; +#[cfg(all(feature = "std", not(feature = "alloc")))] +use std::borrow::Cow; + +#[cfg(feature = "alloc")] +use alloc::boxed::Box; + +#[cfg(feature = "alloc")] +use alloc::vec::Vec; + +/// Types that can be deserialized via `#[serde(with = "serde_bytes")]`. +pub trait Deserialize<'de>: Sized { + #[allow(missing_docs)] + fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> + where + D: Deserializer<'de>; +} + +impl<'de: 'a, 'a> Deserialize<'de> for &'a [u8] { + fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> + where + D: Deserializer<'de>, + { + // Via the serde::Deserialize impl for &[u8]. + serde::Deserialize::deserialize(deserializer) + } +} + +#[cfg(any(feature = "std", feature = "alloc"))] +impl<'de> Deserialize<'de> for Vec<u8> { + fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> + where + D: Deserializer<'de>, + { + Deserialize::deserialize(deserializer).map(ByteBuf::into_vec) + } +} + +impl<'de: 'a, 'a> Deserialize<'de> for &'a Bytes { + fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> + where + D: Deserializer<'de>, + { + Deserialize::deserialize(deserializer).map(Bytes::new) + } +} + +#[cfg(any(feature = "std", feature = "alloc"))] +impl<'de> Deserialize<'de> for ByteBuf { + fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> + where + D: Deserializer<'de>, + { + // Via the serde::Deserialize impl for ByteBuf. + serde::Deserialize::deserialize(deserializer) + } +} + +#[cfg(any(feature = "std", feature = "alloc"))] +impl<'de: 'a, 'a> Deserialize<'de> for Cow<'a, [u8]> { + fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> + where + D: Deserializer<'de>, + { + Deserialize::deserialize(deserializer).map(Cow::Borrowed) + } +} + +#[cfg(any(feature = "std", feature = "alloc"))] +impl<'de: 'a, 'a> Deserialize<'de> for Cow<'a, Bytes> { + fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> + where + D: Deserializer<'de>, + { + Deserialize::deserialize(deserializer).map(Cow::Borrowed) + } +} + +#[cfg(any(feature = "std", feature = "alloc"))] +impl<'de> Deserialize<'de> for Box<[u8]> { + fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> + where + D: Deserializer<'de>, + { + Deserialize::deserialize(deserializer).map(Vec::into_boxed_slice) + } +} + +#[cfg(any(feature = "std", feature = "alloc"))] +impl<'de> Deserialize<'de> for Box<Bytes> { + fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> + where + D: Deserializer<'de>, + { + let bytes: Box<[u8]> = Deserialize::deserialize(deserializer)?; + Ok(bytes.into()) + } +} diff --git a/third_party/rust/serde_bytes/src/lib.rs b/third_party/rust/serde_bytes/src/lib.rs new file mode 100644 index 0000000000..9912623c2f --- /dev/null +++ b/third_party/rust/serde_bytes/src/lib.rs @@ -0,0 +1,108 @@ +//! Wrapper types to enable optimized handling of `&[u8]` and `Vec<u8>`. +//! +//! Without specialization, Rust forces Serde to treat `&[u8]` just like any +//! other slice and `Vec<u8>` just like any other vector. In reality this +//! particular slice and vector can often be serialized and deserialized in a +//! more efficient, compact representation in many formats. +//! +//! When working with such a format, you can opt into specialized handling of +//! `&[u8]` by wrapping it in `serde_bytes::Bytes` and `Vec<u8>` by wrapping it +//! in `serde_bytes::ByteBuf`. +//! +//! Additionally this crate supports the Serde `with` attribute to enable +//! efficient handling of `&[u8]` and `Vec<u8>` in structs without needing a +//! wrapper type. +//! +//! ``` +//! # use serde_derive::{Deserialize, Serialize}; +//! use serde::{Deserialize, Serialize}; +//! +//! #[derive(Deserialize, Serialize)] +//! struct Efficient<'a> { +//! #[serde(with = "serde_bytes")] +//! bytes: &'a [u8], +//! +//! #[serde(with = "serde_bytes")] +//! byte_buf: Vec<u8>, +//! } +//! ``` + +#![doc(html_root_url = "https://docs.rs/serde_bytes/0.11.2")] +#![cfg_attr(not(feature = "std"), no_std)] +#![deny(missing_docs)] + +mod bytes; +mod de; +mod ser; + +#[cfg(any(feature = "std", feature = "alloc"))] +mod bytebuf; + +#[cfg(feature = "alloc")] +extern crate alloc; + +#[cfg(any(feature = "std", feature = "alloc"))] +use serde::Deserializer; + +use serde::Serializer; + +pub use crate::bytes::Bytes; +pub use crate::de::Deserialize; +pub use crate::ser::Serialize; + +#[cfg(any(feature = "std", feature = "alloc"))] +pub use crate::bytebuf::ByteBuf; + +/// Serde `serialize_with` function to serialize bytes efficiently. +/// +/// This function can be used with either of the following Serde attributes: +/// +/// - `#[serde(with = "serde_bytes")]` +/// - `#[serde(serialize_with = "serde_bytes::serialize")]` +/// +/// ``` +/// # use serde_derive::Serialize; +/// use serde::Serialize; +/// +/// #[derive(Serialize)] +/// struct Efficient<'a> { +/// #[serde(with = "serde_bytes")] +/// bytes: &'a [u8], +/// +/// #[serde(with = "serde_bytes")] +/// byte_buf: Vec<u8>, +/// } +/// ``` +pub fn serialize<T, S>(bytes: &T, serializer: S) -> Result<S::Ok, S::Error> +where + T: ?Sized + Serialize, + S: Serializer, +{ + Serialize::serialize(bytes, serializer) +} + +/// Serde `deserialize_with` function to deserialize bytes efficiently. +/// +/// This function can be used with either of the following Serde attributes: +/// +/// - `#[serde(with = "serde_bytes")]` +/// - `#[serde(deserialize_with = "serde_bytes::deserialize")]` +/// +/// ``` +/// # use serde_derive::Deserialize; +/// use serde::Deserialize; +/// +/// #[derive(Deserialize)] +/// struct Packet { +/// #[serde(with = "serde_bytes")] +/// payload: Vec<u8>, +/// } +/// ``` +#[cfg(any(feature = "std", feature = "alloc"))] +pub fn deserialize<'de, T, D>(deserializer: D) -> Result<T, D::Error> +where + T: Deserialize<'de>, + D: Deserializer<'de>, +{ + Deserialize::deserialize(deserializer) +} diff --git a/third_party/rust/serde_bytes/src/ser.rs b/third_party/rust/serde_bytes/src/ser.rs new file mode 100644 index 0000000000..808ef96760 --- /dev/null +++ b/third_party/rust/serde_bytes/src/ser.rs @@ -0,0 +1,107 @@ +use crate::Bytes; +use serde::Serializer; + +#[cfg(any(feature = "std", feature = "alloc"))] +use crate::ByteBuf; + +#[cfg(feature = "alloc")] +use alloc::borrow::Cow; +#[cfg(all(feature = "std", not(feature = "alloc")))] +use std::borrow::Cow; + +#[cfg(feature = "alloc")] +use alloc::boxed::Box; + +#[cfg(feature = "alloc")] +use alloc::vec::Vec; + +/// Types that can be serialized via `#[serde(with = "serde_bytes")]`. +pub trait Serialize { + #[allow(missing_docs)] + fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> + where + S: Serializer; +} + +impl Serialize for [u8] { + fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> + where + S: Serializer, + { + serializer.serialize_bytes(self) + } +} + +#[cfg(any(feature = "std", feature = "alloc"))] +impl Serialize for Vec<u8> { + fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> + where + S: Serializer, + { + serializer.serialize_bytes(self) + } +} + +impl Serialize for Bytes { + fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> + where + S: Serializer, + { + serializer.serialize_bytes(self) + } +} + +#[cfg(any(feature = "std", feature = "alloc"))] +impl Serialize for ByteBuf { + fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> + where + S: Serializer, + { + serializer.serialize_bytes(self) + } +} + +#[cfg(any(feature = "std", feature = "alloc"))] +impl<'a> Serialize for Cow<'a, [u8]> { + fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> + where + S: Serializer, + { + serializer.serialize_bytes(self) + } +} + +#[cfg(any(feature = "std", feature = "alloc"))] +impl<'a> Serialize for Cow<'a, Bytes> { + fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> + where + S: Serializer, + { + serializer.serialize_bytes(self) + } +} + +impl<'a, T> Serialize for &'a T +where + T: ?Sized + Serialize, +{ + fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> + where + S: Serializer, + { + (**self).serialize(serializer) + } +} + +#[cfg(any(feature = "std", feature = "alloc"))] +impl<T> Serialize for Box<T> +where + T: ?Sized + Serialize, +{ + fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> + where + S: Serializer, + { + (**self).serialize(serializer) + } +} |