summaryrefslogtreecommitdiff
path: root/src/de.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/de.rs')
-rw-r--r--src/de.rs229
1 files changed, 229 insertions, 0 deletions
diff --git a/src/de.rs b/src/de.rs
new file mode 100644
index 0000000..e4a4732
--- /dev/null
+++ b/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)
+ }
+}