summaryrefslogtreecommitdiffstats
path: root/third_party/rust/serde_bytes/src
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/serde_bytes/src')
-rw-r--r--third_party/rust/serde_bytes/src/bytebuf.rs253
-rw-r--r--third_party/rust/serde_bytes/src/bytes.rs172
-rw-r--r--third_party/rust/serde_bytes/src/de.rs229
-rw-r--r--third_party/rust/serde_bytes/src/lib.rs113
-rw-r--r--third_party/rust/serde_bytes/src/ser.rs136
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(),
+ }
+ }
+}