diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
commit | 36d22d82aa202bb199967e9512281e9a53db42c9 (patch) | |
tree | 105e8c98ddea1c1e4784a60a5a6410fa416be2de /third_party/rust/serde_bytes/src | |
parent | Initial commit. (diff) | |
download | firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.tar.xz firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.zip |
Adding upstream version 115.7.0esr.upstream/115.7.0esr
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 | 253 | ||||
-rw-r--r-- | third_party/rust/serde_bytes/src/bytes.rs | 172 | ||||
-rw-r--r-- | third_party/rust/serde_bytes/src/de.rs | 229 | ||||
-rw-r--r-- | third_party/rust/serde_bytes/src/lib.rs | 113 | ||||
-rw-r--r-- | third_party/rust/serde_bytes/src/ser.rs | 136 |
5 files changed, 903 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..0c2daa6e25 --- /dev/null +++ b/third_party/rust/serde_bytes/src/bytebuf.rs @@ -0,0 +1,253 @@ +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)] + #[allow(clippy::should_implement_trait)] + 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 bytes = Vec::with_capacity(len); + + while let Some(b) = visitor.next_element()? { + bytes.push(b); + } + + Ok(ByteBuf::from(bytes)) + } + + 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..ad0902b434 --- /dev/null +++ b/third_party/rust/serde_bytes/src/bytes.rs @@ -0,0 +1,172 @@ +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}; +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)] +#[cfg_attr(not(doc), repr(transparent))] +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) + } +} + +impl<'a, 'de: 'a> Deserialize<'de> for &'a Bytes { + fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> + where + D: Deserializer<'de>, + { + // serde::Deserialize for &[u8] is already optimized, so simply forward to that. + Deserialize::deserialize(deserializer).map(Bytes::new) + } +} 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..e4a4732eea --- /dev/null +++ b/third_party/rust/serde_bytes/src/de.rs @@ -0,0 +1,229 @@ +use crate::Bytes; +use core::fmt; +use core::marker::PhantomData; +use serde::de::{Error, Visitor}; +use serde::Deserializer; + +#[cfg(any(feature = "std", feature = "alloc"))] +use crate::ByteBuf; + +#[cfg(any(feature = "std", feature = "alloc"))] +use core::cmp; + +#[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::string::String; +#[cfg(feature = "alloc")] +use alloc::vec::Vec; + +#[cfg(any(feature = "std", feature = "alloc"))] +use serde::de::SeqAccess; + +/// 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>, + { + // serde::Deserialize for &[u8] is already optimized, so simply forward to that. + 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>, + { + // serde::Deserialize for &[u8] is already optimized, so simply forward to that. + serde::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>, + { + struct CowVisitor; + + impl<'de> Visitor<'de> for CowVisitor { + type Value = Cow<'de, [u8]>; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("a byte array") + } + + fn visit_borrowed_bytes<E>(self, v: &'de [u8]) -> Result<Self::Value, E> + where + E: Error, + { + Ok(Cow::Borrowed(v)) + } + + fn visit_borrowed_str<E>(self, v: &'de str) -> Result<Self::Value, E> + where + E: Error, + { + Ok(Cow::Borrowed(v.as_bytes())) + } + + fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E> + where + E: Error, + { + Ok(Cow::Owned(v.to_vec())) + } + + fn visit_str<E>(self, v: &str) -> Result<Self::Value, E> + where + E: Error, + { + Ok(Cow::Owned(v.as_bytes().to_vec())) + } + + fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E> + where + E: Error, + { + Ok(Cow::Owned(v)) + } + + fn visit_string<E>(self, v: String) -> Result<Self::Value, E> + where + E: Error, + { + Ok(Cow::Owned(v.into_bytes())) + } + + fn visit_seq<V>(self, mut visitor: V) -> Result<Self::Value, V::Error> + where + V: SeqAccess<'de>, + { + let len = cmp::min(visitor.size_hint().unwrap_or(0), 4096); + let mut bytes = Vec::with_capacity(len); + + while let Some(b) = visitor.next_element()? { + bytes.push(b); + } + + Ok(Cow::Owned(bytes)) + } + } + + deserializer.deserialize_bytes(CowVisitor) + } +} + +#[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>, + { + let cow: Cow<[u8]> = Deserialize::deserialize(deserializer)?; + match cow { + Cow::Borrowed(bytes) => Ok(Cow::Borrowed(Bytes::new(bytes))), + Cow::Owned(bytes) => Ok(Cow::Owned(ByteBuf::from(bytes))), + } + } +} + +#[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()) + } +} + +impl<'de, T> Deserialize<'de> for Option<T> +where + T: Deserialize<'de>, +{ + fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> + where + D: Deserializer<'de>, + { + struct BytesVisitor<T> { + out: PhantomData<T>, + } + + impl<'de, T> Visitor<'de> for BytesVisitor<T> + where + T: Deserialize<'de>, + { + type Value = Option<T>; + + fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.write_str("optional byte array") + } + + fn visit_unit<E: Error>(self) -> Result<Self::Value, E> { + Ok(None) + } + + fn visit_none<E: Error>(self) -> Result<Self::Value, E> { + Ok(None) + } + + fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error> + where + D: Deserializer<'de>, + { + T::deserialize(deserializer).map(Some) + } + } + + let visitor = BytesVisitor { out: PhantomData }; + deserializer.deserialize_option(visitor) + } +} 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..871d6cbcb9 --- /dev/null +++ b/third_party/rust/serde_bytes/src/lib.rs @@ -0,0 +1,113 @@ +//! 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.9")] +#![cfg_attr(not(feature = "std"), no_std)] +#![deny(missing_docs)] +#![allow( + clippy::missing_errors_doc, + clippy::must_use_candidate, + clippy::needless_doctest_main +)] + +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..1cbed9f757 --- /dev/null +++ b/third_party/rust/serde_bytes/src/ser.rs @@ -0,0 +1,136 @@ +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) + } +} + +impl<T> Serialize for Option<T> +where + T: Serialize, +{ + fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> + where + S: Serializer, + { + struct AsBytes<T>(T); + + impl<T> serde::Serialize for AsBytes<T> + where + T: Serialize, + { + fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> + where + S: Serializer, + { + self.0.serialize(serializer) + } + } + + match self { + Some(b) => serializer.serialize_some(&AsBytes(b)), + None => serializer.serialize_none(), + } + } +} |