From 295abcf90079dabc2d0842557fa879a3e02e036c Mon Sep 17 00:00:00 2001 From: SF-Zhou Date: Wed, 22 Jan 2025 10:12:50 +0800 Subject: [PATCH 1/6] support char --- derse/src/error.rs | 2 ++ derse/src/serialization.rs | 26 ++++++++++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/derse/src/error.rs b/derse/src/error.rs index b2f9420..b500d44 100644 --- a/derse/src/error.rs +++ b/derse/src/error.rs @@ -16,6 +16,8 @@ pub enum Error { InvalidType(String), #[error("invalid value: {0}")] InvalidValue(String), + #[error("invalid char: {0}")] + InvalidChar(u32), } impl Default for Error { diff --git a/derse/src/serialization.rs b/derse/src/serialization.rs index a4c609d..b47ea5e 100644 --- a/derse/src/serialization.rs +++ b/derse/src/serialization.rs @@ -145,6 +145,22 @@ impl<'a> Deserialize<'a> for usize { } } +impl Serialize for char { + fn serialize_to(&self, serializer: &mut S) -> Result<()> { + (*self as u32).serialize_to(serializer) + } +} + +impl<'a> Deserialize<'a> for char { + fn deserialize_from>(buf: &mut D) -> Result + where + Self: Sized, + { + let c = u32::deserialize_from(buf)?; + char::from_u32(c).ok_or_else(|| Error::InvalidChar(c)) + } +} + impl Serialize for str { fn serialize_to(&self, serializer: &mut S) -> Result<()> { serializer.prepend(self.as_bytes())?; @@ -443,6 +459,16 @@ mod tests { "data is short for deserialize: expect 1, actual 0".to_owned() ); + { + let ser = '😊'; + let bytes: DownwardBytes = ser.serialize().unwrap(); + let der = char::deserialize(&bytes[..]).unwrap(); + assert_eq!(ser, der); + + char::deserialize([0xff].as_slice()).unwrap_err(); + char::deserialize([0, 0, 0x11, 0].as_slice()).unwrap_err(); + } + { let ser = "hello world!"; let bytes: DownwardBytes = ser.serialize().unwrap(); From 568f1784fb74e6ce5b853fd1518929aba15c5bcd Mon Sep 17 00:00:00 2001 From: SF-Zhou Date: Wed, 22 Jan 2025 10:22:55 +0800 Subject: [PATCH 2/6] support isize --- derse/src/serialization.rs | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/derse/src/serialization.rs b/derse/src/serialization.rs index b47ea5e..3557246 100644 --- a/derse/src/serialization.rs +++ b/derse/src/serialization.rs @@ -145,6 +145,21 @@ impl<'a> Deserialize<'a> for usize { } } +impl Serialize for isize { + fn serialize_to(&self, serializer: &mut S) -> Result<()> { + (*self as i64).serialize_to(serializer) + } +} + +impl<'a> Deserialize<'a> for isize { + fn deserialize_from>(buf: &mut D) -> Result + where + Self: Sized, + { + i64::deserialize_from(buf).map(|v| v as isize) + } +} + impl Serialize for char { fn serialize_to(&self, serializer: &mut S) -> Result<()> { (*self as u32).serialize_to(serializer) @@ -459,6 +474,15 @@ mod tests { "data is short for deserialize: expect 1, actual 0".to_owned() ); + { + let ser = 233isize; + let bytes: DownwardBytes = ser.serialize().unwrap(); + let der = isize::deserialize(&bytes[..]).unwrap(); + assert_eq!(ser, der); + + isize::deserialize([0xff].as_slice()).unwrap_err(); + } + { let ser = '😊'; let bytes: DownwardBytes = ser.serialize().unwrap(); From d5a69dd67aab0a22383bbc9e29a10365dff2a8ca Mon Sep 17 00:00:00 2001 From: SF-Zhou Date: Thu, 23 Jan 2025 11:29:32 +0800 Subject: [PATCH 3/6] support cstr --- derse/src/error.rs | 2 ++ derse/src/impl/cstr.rs | 58 ++++++++++++++++++++++++++++++++++++++ derse/src/impl/mod.rs | 1 + derse/src/serialization.rs | 22 ++++++++++++--- 4 files changed, 79 insertions(+), 4 deletions(-) create mode 100644 derse/src/impl/cstr.rs diff --git a/derse/src/error.rs b/derse/src/error.rs index b500d44..d757044 100644 --- a/derse/src/error.rs +++ b/derse/src/error.rs @@ -10,6 +10,8 @@ pub enum Error { InvalidBool(u8), #[error("invalid string: {0:?}")] InvalidString(Vec), + #[error("invalid cstr: {0}")] + InvalidCStr(String), #[error("varint is short")] VarintIsShort, #[error("invalid type: {0}")] diff --git a/derse/src/impl/cstr.rs b/derse/src/impl/cstr.rs new file mode 100644 index 0000000..2ec625f --- /dev/null +++ b/derse/src/impl/cstr.rs @@ -0,0 +1,58 @@ +use crate::*; +use std::ffi::{CStr, CString}; + +impl Serialize for CStr { + fn serialize_to(&self, serializer: &mut S) -> Result<()> { + self.to_bytes_with_nul().serialize_to(serializer) + } +} + +impl<'a> Deserialize<'a> for &'a CStr { + fn deserialize_from>(buf: &mut D) -> Result + where + Self: Sized, + { + let bytes: &[u8] = Deserialize::deserialize_from(buf)?; + CStr::from_bytes_with_nul(bytes).map_err(|e| Error::InvalidCStr(e.to_string())) + } +} + +impl Serialize for CString { + fn serialize_to(&self, serializer: &mut S) -> Result<()> { + self.as_ref().serialize_to(serializer) + } +} + +impl<'a> Deserialize<'a> for CString { + fn deserialize_from>(buf: &mut D) -> Result + where + Self: Sized, + { + let bytes: Vec = Deserialize::deserialize_from(buf)?; + CString::from_vec_with_nul(bytes).map_err(|e| Error::InvalidCStr(e.to_string())) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_os_str() { + let ser = CStr::from_bytes_with_nul(b"hello\0").unwrap(); + assert_eq!(ser.count_bytes(), 5); + let bytes = ser.serialize::().unwrap(); + assert_eq!(bytes.len(), 7); + let der = <&CStr>::deserialize(&bytes[..]).unwrap(); + assert_eq!(ser, der); + + let der = CString::deserialize(&bytes[..]).unwrap(); + assert_eq!(ser, der.as_c_str()); + + let ser = ser.to_owned(); + let bytes = ser.serialize::().unwrap(); + assert_eq!(bytes.len(), 7); + let der = CString::deserialize(&bytes[..]).unwrap(); + assert_eq!(ser, der); + } +} diff --git a/derse/src/impl/mod.rs b/derse/src/impl/mod.rs index 7bc62c0..5874053 100644 --- a/derse/src/impl/mod.rs +++ b/derse/src/impl/mod.rs @@ -1,3 +1,4 @@ +mod cstr; mod duration; mod osstr; mod pathbuf; diff --git a/derse/src/serialization.rs b/derse/src/serialization.rs index 3557246..a9feda6 100644 --- a/derse/src/serialization.rs +++ b/derse/src/serialization.rs @@ -172,7 +172,7 @@ impl<'a> Deserialize<'a> for char { Self: Sized, { let c = u32::deserialize_from(buf)?; - char::from_u32(c).ok_or_else(|| Error::InvalidChar(c)) + char::from_u32(c).ok_or(Error::InvalidChar(c)) } } @@ -207,6 +207,20 @@ impl Serialize for [u8] { } } +impl<'a> Deserialize<'a> for &'a [u8] { + fn deserialize_from>(buf: &mut D) -> Result + where + Self: Sized, + { + let len = VarInt64::deserialize_from(buf)?.0 as usize; + let front = buf.pop(len)?; + match front { + Cow::Borrowed(borrowed) => Ok(borrowed), + Cow::Owned(_) => Err(Error::InvalidString(Default::default())), + } + } +} + impl Serialize for [u8; N] { fn serialize_to(&self, serializer: &mut S) -> Result<()> { serializer.prepend(self) @@ -225,7 +239,7 @@ impl<'a, const N: usize> Deserialize<'a> for [u8; N] { } } -impl<'a> Serialize for Cow<'a, [u8]> { +impl Serialize for Cow<'_, [u8]> { fn serialize_to(&self, serializer: &mut S) -> Result<()> { <[u8]>::serialize_to(self, serializer) } @@ -241,7 +255,7 @@ impl<'a> Deserialize<'a> for Cow<'a, [u8]> { } } -impl<'a> Serialize for Cow<'a, str> { +impl Serialize for Cow<'_, str> { fn serialize_to(&self, serializer: &mut S) -> Result<()> { self.as_ref().serialize_to(serializer) } @@ -267,7 +281,7 @@ impl<'a> Deserialize<'a> for Cow<'a, str> { } } -impl<'a, T: ToOwned + Serialize> Serialize for Cow<'a, T> { +impl + Serialize> Serialize for Cow<'_, T> { fn serialize_to(&self, serializer: &mut S) -> Result<()> { self.as_ref().serialize_to(serializer) } From ab5a35fb2ecb89f9fe374d758237ab95fb74e912 Mon Sep 17 00:00:00 2001 From: SF-Zhou Date: Thu, 23 Jan 2025 11:47:29 +0800 Subject: [PATCH 4/6] support tuple size = 16 --- derse/src/impl/mod.rs | 1 + derse/src/impl/tuple.rs | 68 ++++++++++++++++++++++++++++++++++++++ derse/src/serialization.rs | 34 ------------------- 3 files changed, 69 insertions(+), 34 deletions(-) create mode 100644 derse/src/impl/tuple.rs diff --git a/derse/src/impl/mod.rs b/derse/src/impl/mod.rs index 5874053..c29d148 100644 --- a/derse/src/impl/mod.rs +++ b/derse/src/impl/mod.rs @@ -5,6 +5,7 @@ mod pathbuf; mod phantom_data; mod result; mod socket_addr; +mod tuple; #[cfg(feature = "compact_str")] mod compact_str; diff --git a/derse/src/impl/tuple.rs b/derse/src/impl/tuple.rs new file mode 100644 index 0000000..8c58f0f --- /dev/null +++ b/derse/src/impl/tuple.rs @@ -0,0 +1,68 @@ +use crate::*; + +macro_rules! tuple_serialization { + (($($name:ident),+), ($($idx:tt),+)) => { + impl<'a, $($name),+> Serialize for ($($name,)+) + where + $($name: Serialize),+ + { + fn serialize_to(&self, serializer: &mut S) -> Result<()> { + $((self.$idx.serialize_to(serializer))?;)+ + Ok(()) + } + } + + impl<'a, $($name),+> Deserialize<'a> for ($($name,)+) + where + $($name: Deserialize<'a>),+ + { + fn deserialize_from>(buf: &mut D) -> Result + where + Self: Sized, + { + Ok(($($name::deserialize_from(buf)?,)+)) + } + } + }; +} + +tuple_serialization!((T0), (0)); +tuple_serialization!((T0, T1), (1, 0)); +tuple_serialization!((T0, T1, T2), (2, 1, 0)); +tuple_serialization!((T0, T1, T2, T3), (3, 2, 1, 0)); +tuple_serialization!((T0, T1, T2, T3, T4), (4, 3, 2, 1, 0)); +tuple_serialization!((T0, T1, T2, T3, T4, T5), (5, 4, 3, 2, 1, 0)); +tuple_serialization!((T0, T1, T2, T3, T4, T5, T6), (6, 5, 4, 3, 2, 1, 0)); +tuple_serialization!((T0, T1, T2, T3, T4, T5, T6, T7), (7, 6, 5, 4, 3, 2, 1, 0)); +tuple_serialization!( + (T0, T1, T2, T3, T4, T5, T6, T7, T8), + (8, 7, 6, 5, 4, 3, 2, 1, 0) +); +tuple_serialization!( + (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9), + (9, 8, 7, 6, 5, 4, 3, 2, 1, 0) +); +tuple_serialization!( + (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10), + (10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0) +); +tuple_serialization!( + (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11), + (11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0) +); +tuple_serialization!( + (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12), + (12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0) +); +tuple_serialization!( + (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13), + (13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0) +); +tuple_serialization!( + (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14), + (14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0) +); +tuple_serialization!( + (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15), + (15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0) +); diff --git a/derse/src/serialization.rs b/derse/src/serialization.rs index a9feda6..a983848 100644 --- a/derse/src/serialization.rs +++ b/derse/src/serialization.rs @@ -428,40 +428,6 @@ impl<'a> Deserialize<'a> for () { } } -macro_rules! tuple_serialization { - (($($name:ident),+), ($($idx:tt),+)) => { - impl<'a, $($name),+> Serialize for ($($name,)+) - where - $($name: Serialize),+ - { - fn serialize_to(&self, serializer: &mut S) -> Result<()> { - $((self.$idx.serialize_to(serializer))?;)+ - Ok(()) - } - } - - impl<'a, $($name),+> Deserialize<'a> for ($($name,)+) - where - $($name: Deserialize<'a>),+ - { - fn deserialize_from>(buf: &mut D) -> Result - where - Self: Sized, - { - Ok(($($name::deserialize_from(buf)?,)+)) - } - } - }; -} - -tuple_serialization!((H), (0)); -tuple_serialization!((H, I), (1, 0)); -tuple_serialization!((H, I, J), (2, 1, 0)); -tuple_serialization!((H, I, J, K), (3, 2, 1, 0)); -tuple_serialization!((H, I, J, K, L), (4, 3, 2, 1, 0)); -tuple_serialization!((H, I, J, K, L, M), (5, 4, 3, 2, 1, 0)); -tuple_serialization!((H, I, J, K, L, M, N), (6, 5, 4, 3, 2, 1, 0)); - #[cfg(test)] mod tests { use super::super::*; From 848f4c3bad5b7ae900d057c4742b9c16ff2a6e8d Mon Sep 17 00:00:00 2001 From: SF-Zhou Date: Thu, 23 Jan 2025 14:58:56 +0800 Subject: [PATCH 5/6] support more collections --- derse/src/impl/collections.rs | 220 ++++++++++++++++++++++++++++++++++ derse/src/impl/mod.rs | 1 + derse/src/lib.rs | 85 ++++++++++++- derse/src/serialization.rs | 219 +-------------------------------- 4 files changed, 306 insertions(+), 219 deletions(-) create mode 100644 derse/src/impl/collections.rs diff --git a/derse/src/impl/collections.rs b/derse/src/impl/collections.rs new file mode 100644 index 0000000..d81df1d --- /dev/null +++ b/derse/src/impl/collections.rs @@ -0,0 +1,220 @@ +use crate::*; +use std::cmp::Eq; +use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, LinkedList, VecDeque}; +use std::hash::Hash; + +macro_rules! seq_se_rev_impl { + ( + $ty:ident + ) => { + impl Serialize for $ty + where + T: Serialize, + { + #[inline] + fn serialize_to(&self, serializer: &mut S) -> Result<()> { + for item in self.iter().rev() { + item.serialize_to(serializer)?; + } + VarInt64(self.len() as u64).serialize_to(serializer) + } + } + }; +} + +seq_se_rev_impl! { + Vec +} + +seq_se_rev_impl! { + VecDeque +} + +seq_se_rev_impl! { + LinkedList +} + +seq_se_rev_impl! { + BinaryHeap +} + +macro_rules! seq_se_for_impl { + ( + $ty:ident + ) => { + impl Serialize for $ty + where + T: Serialize, + { + #[inline] + fn serialize_to(&self, serializer: &mut S) -> Result<()> { + for item in self.iter() { + item.serialize_to(serializer)?; + } + VarInt64(self.len() as u64).serialize_to(serializer) + } + } + }; +} + +seq_se_for_impl! { + BTreeSet +} + +seq_se_for_impl! { + HashSet +} + +macro_rules! seq_de_impl { + ( + $ty:ident + ) => { + impl<'a, T> Deserialize<'a> for $ty + where + T: Deserialize<'a> $(+ $tbound1 $(+ $tbound2)*)*, + { + fn deserialize_from>(buf: &mut D) -> Result + where + Self: Sized, + { + let len = VarInt64::deserialize_from(buf)?.0 as usize; + (0..len).map(|_| T::deserialize_from(buf)).collect::>() + } + } + }; +} + +seq_de_impl! { + Vec +} + +seq_de_impl! { + VecDeque +} + +seq_de_impl! { + LinkedList +} + +seq_de_impl! { + BinaryHeap +} + +seq_de_impl! { + BTreeSet +} + +seq_de_impl! { + HashSet +} + +macro_rules! map_impl { + ( + $ty:ident + ) => { + impl Serialize for $ty + where + K: Serialize, + V: Serialize, + { + #[inline] + fn serialize_to(&self, serializer: &mut S) -> Result<()> { + for item in self.iter() { + item.serialize_to(serializer)?; + } + VarInt64(self.len() as u64).serialize_to(serializer) + } + } + + impl<'a, K, V> Deserialize<'a> for $ty + where + Self: Sized, + K: Deserialize<'a> $(+ $kbound1 $(+ $kbound2)*)*, + V: Deserialize<'a>, + { + #[inline] + fn deserialize_from>(buf: &mut D) -> Result + where + Self: Sized, + { + let len = VarInt64::deserialize_from(buf)?.0 as usize; + (0..len).map(|_| <(K, V)>::deserialize_from(buf)).collect::>() + } + } + } +} + +map_impl! { + BTreeMap +} + +map_impl! { + HashMap +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_collections() { + { + let ser = vec!["hello", "world", "!"]; + let bytes: DownwardBytes = ser.serialize().unwrap(); + let der = Vec::::deserialize(&bytes[..]).unwrap(); + assert_eq!(ser, der); + + assert!(Vec::::deserialize([128].as_ref()).is_err()); + assert!(Vec::::deserialize([1].as_ref()).is_err()); + assert!(Vec::::deserialize([0].as_ref()).unwrap().is_empty()); + } + + { + let ser = Some("hello".to_string()); + let bytes: DownwardBytes = ser.serialize().unwrap(); + assert_eq!(bytes.len(), 1 + 1 + 5); + let der = Option::::deserialize(&bytes[..]).unwrap(); + assert_eq!(ser, der); + let der = Vec::::deserialize(&bytes[..]).unwrap(); + assert_eq!(ser.as_ref(), der.first()); + + let ser = None; + let bytes: DownwardBytes = ser.serialize().unwrap(); + assert_eq!(bytes.len(), 1); + let der = Option::::deserialize(&bytes[..]).unwrap(); + assert_eq!(ser, der); + let der = Vec::::deserialize(&bytes[..]).unwrap(); + assert_eq!(ser.as_ref(), der.first()); + + assert!(Option::::deserialize([128].as_ref()).is_err()); + assert!(Option::::deserialize([1].as_ref()).is_err()); + assert!(Option::::deserialize([0].as_ref()) + .unwrap() + .is_none()); + } + + { + let ser: HashSet = "hello world !".split(' ').map(|s| s.to_owned()).collect(); + let bytes: DownwardBytes = ser.serialize().unwrap(); + let der = HashSet::::deserialize(&bytes[..]).unwrap(); + assert_eq!(ser, der); + + assert!(HashSet::::deserialize([128].as_ref()).is_err()); + assert!(HashSet::::deserialize([1].as_ref()).is_err()); + assert!(HashSet::::deserialize([0].as_ref()).unwrap().is_empty()); + } + + { + let ser: HashMap = (0..10).map(|i| (i.to_string(), i)).collect(); + let bytes: DownwardBytes = ser.serialize().unwrap(); + let der = HashMap::::deserialize(&bytes[..]).unwrap(); + assert_eq!(ser, der); + + let mut der = Vec::<(String, u32)>::deserialize(&bytes[..]).unwrap(); + assert_eq!(der.len(), 10); + der.sort(); + assert_eq!(der[0].0, "0"); + assert_eq!(der[9].0, "9"); + } + } +} diff --git a/derse/src/impl/mod.rs b/derse/src/impl/mod.rs index c29d148..834f895 100644 --- a/derse/src/impl/mod.rs +++ b/derse/src/impl/mod.rs @@ -1,3 +1,4 @@ +mod collections; mod cstr; mod duration; mod osstr; diff --git a/derse/src/lib.rs b/derse/src/lib.rs index 1d976f6..e37aa54 100644 --- a/derse/src/lib.rs +++ b/derse/src/lib.rs @@ -11,8 +11,91 @@ pub use bytes_array::BytesArray; pub use deserializer::Deserializer; pub use downward_bytes::DownwardBytes; pub use error::{Error, Result}; -pub use serialization::{Deserialize, DetailedDeserialize, Serialize}; pub use serializer::Serializer; pub use varint64::VarInt64; pub use derse_derive::{Deserialize, Serialize}; + +/// A trait for serializing data. +pub trait Serialize { + /// Serializes the data into a new `Serializer` instance. + /// + /// # Returns + /// + /// A `Result` containing the serialized data or an error. + fn serialize(&self) -> Result { + let mut serializer = S::default(); + self.serialize_to(&mut serializer)?; + Ok(serializer) + } + + /// Serializes the data into the given `Serializer`. + /// + /// # Arguments + /// + /// * `serializer` - The `Serializer` to serialize the data into. + /// + /// # Returns + /// + /// A `Result` indicating success or failure. + fn serialize_to(&self, serializer: &mut S) -> Result<()>; +} + +/// A trait for deserializing data. +pub trait Deserialize<'a> { + /// Deserializes the data from a `Deserializer`. + /// + /// # Arguments + /// + /// * `der` - The `Deserializer` to deserialize the data from. + /// + /// # Returns + /// + /// A `Result` containing the deserialized data or an error. + fn deserialize>(mut der: D) -> Result + where + Self: Sized, + { + Self::deserialize_from(&mut der) + } + + /// Deserializes the data from the given `Deserializer`. + /// + /// # Arguments + /// + /// * `buf` - The `Deserializer` to deserialize the data from. + /// + /// # Returns + /// + /// A `Result` containing the deserialized data or an error. + fn deserialize_from>(buf: &mut D) -> Result + where + Self: Sized; +} + +/// A trait for detailed deserialization. +pub trait DetailedDeserialize<'a> { + /// Deserializes the length from the given `Deserializer`. + /// + /// # Arguments + /// + /// * `buf` - The `Deserializer` to deserialize the length from. + /// + /// # Returns + /// + /// A `Result` containing the length or an error. + fn deserialize_len>(buf: &mut D) -> Result; + + /// Deserializes the fields from the given `Deserializer`. + /// + /// # Arguments + /// + /// * `buf` - The `Deserializer` to deserialize the fields from. + /// + /// # Returns + /// + /// A `Result` containing the deserialized fields or an error. + fn deserialize_fields>(buf: &mut D) -> Result + where + Self: Sized; +} diff --git a/derse/src/serialization.rs b/derse/src/serialization.rs index a983848..21db51c 100644 --- a/derse/src/serialization.rs +++ b/derse/src/serialization.rs @@ -1,92 +1,5 @@ -use super::{Deserializer, Error, Result, Serializer, VarInt64}; +use crate::*; use std::borrow::Cow; -use std::collections::HashMap; -use std::collections::HashSet; -use std::hash::Hash; - -/// A trait for serializing data. -pub trait Serialize { - /// Serializes the data into a new `Serializer` instance. - /// - /// # Returns - /// - /// A `Result` containing the serialized data or an error. - fn serialize(&self) -> Result { - let mut serializer = S::default(); - self.serialize_to(&mut serializer)?; - Ok(serializer) - } - - /// Serializes the data into the given `Serializer`. - /// - /// # Arguments - /// - /// * `serializer` - The `Serializer` to serialize the data into. - /// - /// # Returns - /// - /// A `Result` indicating success or failure. - fn serialize_to(&self, serializer: &mut S) -> Result<()>; -} - -/// A trait for deserializing data. -pub trait Deserialize<'a> { - /// Deserializes the data from a `Deserializer`. - /// - /// # Arguments - /// - /// * `der` - The `Deserializer` to deserialize the data from. - /// - /// # Returns - /// - /// A `Result` containing the deserialized data or an error. - fn deserialize>(mut der: D) -> Result - where - Self: Sized, - { - Self::deserialize_from(&mut der) - } - - /// Deserializes the data from the given `Deserializer`. - /// - /// # Arguments - /// - /// * `buf` - The `Deserializer` to deserialize the data from. - /// - /// # Returns - /// - /// A `Result` containing the deserialized data or an error. - fn deserialize_from>(buf: &mut D) -> Result - where - Self: Sized; -} - -/// A trait for detailed deserialization. -pub trait DetailedDeserialize<'a> { - /// Deserializes the length from the given `Deserializer`. - /// - /// # Arguments - /// - /// * `buf` - The `Deserializer` to deserialize the length from. - /// - /// # Returns - /// - /// A `Result` containing the length or an error. - fn deserialize_len>(buf: &mut D) -> Result; - - /// Deserializes the fields from the given `Deserializer`. - /// - /// # Arguments - /// - /// * `buf` - The `Deserializer` to deserialize the fields from. - /// - /// # Returns - /// - /// A `Result` containing the deserialized fields or an error. - fn deserialize_fields>(buf: &mut D) -> Result - where - Self: Sized; -} macro_rules! impl_serialize_trait { ($($t:ty),*) => { @@ -311,77 +224,6 @@ impl<'a> Deserialize<'a> for String { } } -impl Serialize for Vec { - fn serialize_to(&self, serializer: &mut S) -> Result<()> { - for item in self.iter().rev() { - item.serialize_to(serializer)?; - } - VarInt64(self.len() as u64).serialize_to(serializer) - } -} - -impl<'a, Item: Deserialize<'a>> Deserialize<'a> for Vec { - fn deserialize_from>(buf: &mut D) -> Result - where - Self: Sized, - { - let len = VarInt64::deserialize_from(buf)?.0 as usize; - let mut out = Vec::with_capacity(len); - for _ in 0..len { - out.push(Item::deserialize_from(buf)?); - } - Ok(out) - } -} - -impl Serialize for HashSet { - fn serialize_to(&self, serializer: &mut S) -> Result<()> { - for item in self.iter() { - item.serialize_to(serializer)?; - } - VarInt64(self.len() as u64).serialize_to(serializer) - } -} - -impl<'a, Item: Eq + Hash + Deserialize<'a>> Deserialize<'a> for HashSet { - fn deserialize_from>(buf: &mut D) -> Result - where - Self: Sized, - { - let len = VarInt64::deserialize_from(buf)?.0 as usize; - let mut out = HashSet::with_capacity(len); - for _ in 0..len { - out.insert(Item::deserialize_from(buf)?); - } - Ok(out) - } -} - -impl Serialize for HashMap { - fn serialize_to(&self, serializer: &mut S) -> Result<()> { - for item in self.iter() { - item.serialize_to(serializer)?; - } - VarInt64(self.len() as u64).serialize_to(serializer) - } -} - -impl<'a, K: Eq + Hash + Deserialize<'a>, V: Deserialize<'a>> Deserialize<'a> for HashMap { - fn deserialize_from>(buf: &mut D) -> Result - where - Self: Sized, - { - let len = VarInt64::deserialize_from(buf)?.0 as usize; - let mut out = HashMap::with_capacity(len); - for _ in 0..len { - let key = K::deserialize_from(buf)?; - let value = V::deserialize_from(buf)?; - out.insert(key, value); - } - Ok(out) - } -} - impl Serialize for Option { fn serialize_to(&self, serializer: &mut S) -> Result<()> { if let Some(item) = self { @@ -513,69 +355,10 @@ mod tests { assert!(String::deserialize(&bytes[..5]).is_err()); } - { - let ser = vec!["hello", "world", "!"]; - let bytes: DownwardBytes = ser.serialize().unwrap(); - let der = Vec::::deserialize(&bytes[..]).unwrap(); - assert_eq!(ser, der); - - assert!(Vec::::deserialize([128].as_ref()).is_err()); - assert!(Vec::::deserialize([1].as_ref()).is_err()); - assert!(Vec::::deserialize([0].as_ref()).unwrap().is_empty()); - } - - { - let ser: HashSet = "hello world !".split(' ').map(|s| s.to_owned()).collect(); - let bytes: DownwardBytes = ser.serialize().unwrap(); - let der = HashSet::::deserialize(&bytes[..]).unwrap(); - assert_eq!(ser, der); - - assert!(HashSet::::deserialize([128].as_ref()).is_err()); - assert!(HashSet::::deserialize([1].as_ref()).is_err()); - assert!(HashSet::::deserialize([0].as_ref()).unwrap().is_empty()); - } - - { - let ser = Some("hello".to_string()); - let bytes: DownwardBytes = ser.serialize().unwrap(); - assert_eq!(bytes.len(), 1 + 1 + 5); - let der = Option::::deserialize(&bytes[..]).unwrap(); - assert_eq!(ser, der); - let der = Vec::::deserialize(&bytes[..]).unwrap(); - assert_eq!(ser.as_ref(), der.first()); - - let ser = None; - let bytes: DownwardBytes = ser.serialize().unwrap(); - assert_eq!(bytes.len(), 1); - let der = Option::::deserialize(&bytes[..]).unwrap(); - assert_eq!(ser, der); - let der = Vec::::deserialize(&bytes[..]).unwrap(); - assert_eq!(ser.as_ref(), der.first()); - - assert!(Option::::deserialize([128].as_ref()).is_err()); - assert!(Option::::deserialize([1].as_ref()).is_err()); - assert!(Option::::deserialize([0].as_ref()) - .unwrap() - .is_none()); - } - { assert!(u32::deserialize([0, 1, 2].as_ref()).is_err()); } - { - let ser: HashMap = (0..10).map(|i| (i.to_string(), i)).collect(); - let bytes: DownwardBytes = ser.serialize().unwrap(); - let der = HashMap::::deserialize(&bytes[..]).unwrap(); - assert_eq!(ser, der); - - let mut der = Vec::<(String, u32)>::deserialize(&bytes[..]).unwrap(); - assert_eq!(der.len(), 10); - der.sort(); - assert_eq!(der[0].0, "0"); - assert_eq!(der[9].0, "9"); - } - { let ser = (String::from("hello"), 64u32); let bytes: DownwardBytes = ser.serialize().unwrap(); From ac65bc4e6b2f80e914aadd5650078663de34da13 Mon Sep 17 00:00:00 2001 From: SF-Zhou Date: Thu, 23 Jan 2025 16:39:37 +0800 Subject: [PATCH 6/6] split primitive types --- derse/Cargo.toml | 2 +- derse/src/error.rs | 2 + derse/src/impls/array.rs | 96 +++++ derse/src/{impl => impls}/collections.rs | 7 + derse/src/{impl => impls}/compact_str.rs | 0 derse/src/impls/cow.rs | 59 ++++ derse/src/{impl => impls}/cstr.rs | 0 derse/src/{impl => impls}/duration.rs | 0 derse/src/{impl => impls}/mod.rs | 4 + derse/src/{impl => impls}/osstr.rs | 0 derse/src/{impl => impls}/pathbuf.rs | 0 derse/src/{impl => impls}/phantom_data.rs | 0 derse/src/impls/primitive.rs | 199 +++++++++++ derse/src/{impl => impls}/result.rs | 0 derse/src/{impl => impls}/socket_addr.rs | 0 derse/src/impls/string.rs | 146 ++++++++ derse/src/{impl => impls}/tinyvec.rs | 0 derse/src/{impl => impls}/tuple.rs | 0 derse/src/lib.rs | 3 +- derse/src/serialization.rs | 412 ---------------------- 20 files changed, 515 insertions(+), 415 deletions(-) create mode 100644 derse/src/impls/array.rs rename derse/src/{impl => impls}/collections.rs (96%) rename derse/src/{impl => impls}/compact_str.rs (100%) create mode 100644 derse/src/impls/cow.rs rename derse/src/{impl => impls}/cstr.rs (100%) rename derse/src/{impl => impls}/duration.rs (100%) rename derse/src/{impl => impls}/mod.rs (81%) rename derse/src/{impl => impls}/osstr.rs (100%) rename derse/src/{impl => impls}/pathbuf.rs (100%) rename derse/src/{impl => impls}/phantom_data.rs (100%) create mode 100644 derse/src/impls/primitive.rs rename derse/src/{impl => impls}/result.rs (100%) rename derse/src/{impl => impls}/socket_addr.rs (100%) create mode 100644 derse/src/impls/string.rs rename derse/src/{impl => impls}/tinyvec.rs (100%) rename derse/src/{impl => impls}/tuple.rs (100%) delete mode 100644 derse/src/serialization.rs diff --git a/derse/Cargo.toml b/derse/Cargo.toml index 9f78cea..314401c 100644 --- a/derse/Cargo.toml +++ b/derse/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "derse" -version = "0.1.32" +version = "0.1.33" authors.workspace = true edition.workspace = true homepage.workspace = true diff --git a/derse/src/error.rs b/derse/src/error.rs index d757044..dafe332 100644 --- a/derse/src/error.rs +++ b/derse/src/error.rs @@ -20,6 +20,8 @@ pub enum Error { InvalidValue(String), #[error("invalid char: {0}")] InvalidChar(u32), + #[error("invalid length: {0}, error: {1}")] + InvalidLength(usize, String), } impl Default for Error { diff --git a/derse/src/impls/array.rs b/derse/src/impls/array.rs new file mode 100644 index 0000000..38939be --- /dev/null +++ b/derse/src/impls/array.rs @@ -0,0 +1,96 @@ +use crate::*; + +impl Serialize for [T; N] { + fn serialize_to(&self, serializer: &mut S) -> Result<()> { + for item in self.iter().rev() { + item.serialize_to(serializer)?; + } + Ok(()) + } +} + +macro_rules! array_impls { + ($($len:expr => ($($n:tt)+))+) => { + $( + impl<'a, T: Deserialize<'a>> Deserialize<'a> for [T; $len] { + fn deserialize_from>(buf: &mut D) -> Result + where + Self: Sized, + { + Ok([$( + match T::deserialize_from(buf) { + Ok(val) => val, + Err(e) => return Err(Error::InvalidLength($n, e.to_string())), + } + ),+]) + } + } + )+ + } +} + +array_impls! { + 1 => (0) + 2 => (0 1) + 3 => (0 1 2) + 4 => (0 1 2 3) + 5 => (0 1 2 3 4) + 6 => (0 1 2 3 4 5) + 7 => (0 1 2 3 4 5 6) + 8 => (0 1 2 3 4 5 6 7) + 9 => (0 1 2 3 4 5 6 7 8) + 10 => (0 1 2 3 4 5 6 7 8 9) + 11 => (0 1 2 3 4 5 6 7 8 9 10) + 12 => (0 1 2 3 4 5 6 7 8 9 10 11) + 13 => (0 1 2 3 4 5 6 7 8 9 10 11 12) + 14 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13) + 15 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14) + 16 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15) + 17 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16) + 18 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17) + 19 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18) + 20 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19) + 21 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20) + 22 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21) + 23 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22) + 24 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23) + 25 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24) + 26 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25) + 27 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26) + 28 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27) + 29 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28) + 30 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29) + 31 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30) + 32 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_array() { + { + let ser: [i32; 3] = [1, 2, 3]; + let bytes: DownwardBytes = ser.serialize().unwrap(); + let der = <[i32; 3]>::deserialize(&bytes[..]).unwrap(); + assert_eq!(ser, der); + + <[bool; 3]>::deserialize([].as_slice()).unwrap_err(); + <[bool; 3]>::deserialize([1].as_slice()).unwrap_err(); + <[bool; 3]>::deserialize([2].as_slice()).unwrap_err(); + <[bool; 3]>::deserialize([1, 1].as_slice()).unwrap_err(); + <[bool; 3]>::deserialize([1, 2].as_slice()).unwrap_err(); + <[bool; 3]>::deserialize([1, 1, 1].as_slice()).unwrap(); + <[bool; 3]>::deserialize([1, 1, 2].as_slice()).unwrap_err(); + } + + { + let ser = 233u32; + let bytes = ser.serialize::().unwrap(); + let array = <[u8; 4]>::deserialize(&bytes[..]).unwrap(); + let der = u32::from_le_bytes(array); + assert_eq!(ser, der); + } + } +} diff --git a/derse/src/impl/collections.rs b/derse/src/impls/collections.rs similarity index 96% rename from derse/src/impl/collections.rs rename to derse/src/impls/collections.rs index d81df1d..885f0d2 100644 --- a/derse/src/impl/collections.rs +++ b/derse/src/impls/collections.rs @@ -169,6 +169,13 @@ mod tests { assert!(Vec::::deserialize([0].as_ref()).unwrap().is_empty()); } + { + let ser: LinkedList<_> = (0..10).collect(); + let bytes: DownwardBytes = ser.serialize().unwrap(); + let der = LinkedList::::deserialize(&bytes[..]).unwrap(); + assert_eq!(ser, der); + } + { let ser = Some("hello".to_string()); let bytes: DownwardBytes = ser.serialize().unwrap(); diff --git a/derse/src/impl/compact_str.rs b/derse/src/impls/compact_str.rs similarity index 100% rename from derse/src/impl/compact_str.rs rename to derse/src/impls/compact_str.rs diff --git a/derse/src/impls/cow.rs b/derse/src/impls/cow.rs new file mode 100644 index 0000000..ab7e400 --- /dev/null +++ b/derse/src/impls/cow.rs @@ -0,0 +1,59 @@ +use crate::*; +use std::borrow::Cow; + +impl Serialize for Cow<'_, [u8]> { + fn serialize_to(&self, serializer: &mut S) -> Result<()> { + <[u8]>::serialize_to(self, serializer) + } +} + +impl<'a> Deserialize<'a> for Cow<'a, [u8]> { + fn deserialize_from>(buf: &mut D) -> Result + where + Self: Sized, + { + let len = VarInt64::deserialize_from(buf)?.0 as usize; + buf.pop(len) + } +} + +impl Serialize for Cow<'_, str> { + fn serialize_to(&self, serializer: &mut S) -> Result<()> { + self.as_ref().serialize_to(serializer) + } +} + +impl<'a> Deserialize<'a> for Cow<'a, str> { + fn deserialize_from>(buf: &mut D) -> Result + where + Self: Sized, + { + let len = VarInt64::deserialize_from(buf)?.0 as usize; + let front = buf.pop(len)?; + match front { + Cow::Borrowed(borrowed) => match std::str::from_utf8(borrowed) { + Ok(str) => Ok(Cow::Borrowed(str)), + Err(_) => Err(Error::InvalidString(Vec::from(borrowed))), + }, + Cow::Owned(owned) => match String::from_utf8(owned) { + Ok(str) => Ok(Cow::Owned(str)), + Err(e) => Err(Error::InvalidString(e.into_bytes())), + }, + } + } +} + +impl + Serialize> Serialize for Cow<'_, T> { + fn serialize_to(&self, serializer: &mut S) -> Result<()> { + self.as_ref().serialize_to(serializer) + } +} + +impl<'a, T: ToOwned + Deserialize<'a>> Deserialize<'a> for Cow<'a, T> { + fn deserialize_from>(buf: &mut D) -> Result + where + Self: Sized, + { + Ok(Cow::Owned(T::deserialize_from(buf)?)) + } +} diff --git a/derse/src/impl/cstr.rs b/derse/src/impls/cstr.rs similarity index 100% rename from derse/src/impl/cstr.rs rename to derse/src/impls/cstr.rs diff --git a/derse/src/impl/duration.rs b/derse/src/impls/duration.rs similarity index 100% rename from derse/src/impl/duration.rs rename to derse/src/impls/duration.rs diff --git a/derse/src/impl/mod.rs b/derse/src/impls/mod.rs similarity index 81% rename from derse/src/impl/mod.rs rename to derse/src/impls/mod.rs index 834f895..905c16f 100644 --- a/derse/src/impl/mod.rs +++ b/derse/src/impls/mod.rs @@ -1,11 +1,15 @@ +mod array; mod collections; +mod cow; mod cstr; mod duration; mod osstr; mod pathbuf; mod phantom_data; +mod primitive; mod result; mod socket_addr; +mod string; mod tuple; #[cfg(feature = "compact_str")] diff --git a/derse/src/impl/osstr.rs b/derse/src/impls/osstr.rs similarity index 100% rename from derse/src/impl/osstr.rs rename to derse/src/impls/osstr.rs diff --git a/derse/src/impl/pathbuf.rs b/derse/src/impls/pathbuf.rs similarity index 100% rename from derse/src/impl/pathbuf.rs rename to derse/src/impls/pathbuf.rs diff --git a/derse/src/impl/phantom_data.rs b/derse/src/impls/phantom_data.rs similarity index 100% rename from derse/src/impl/phantom_data.rs rename to derse/src/impls/phantom_data.rs diff --git a/derse/src/impls/primitive.rs b/derse/src/impls/primitive.rs new file mode 100644 index 0000000..df59b52 --- /dev/null +++ b/derse/src/impls/primitive.rs @@ -0,0 +1,199 @@ +use crate::*; + +macro_rules! primitive_impl { + ($($t:ty),*) => { + $(impl Serialize for $t { + fn serialize_to(&self, serializer: &mut S) -> Result<()> { + serializer.prepend(&self.to_le_bytes()) + } + } + + impl<'a> Deserialize<'a> for $t { + fn deserialize_from>(buf: &mut D) -> Result + where + Self: Sized, + { + let front = buf.pop(std::mem::size_of::())?; + Ok(Self::from_le_bytes(front.as_ref().try_into().unwrap())) + } + })* + }; +} + +primitive_impl! {i8, i16, i32, i64, i128, u8, u16, u32, u64, u128, f32, f64} + +impl Serialize for bool { + fn serialize_to(&self, serializer: &mut S) -> Result<()> { + serializer.prepend([*self as u8]) + } +} + +impl<'a> Deserialize<'a> for bool { + fn deserialize_from>(buf: &mut D) -> Result + where + Self: Sized, + { + let front = buf.pop(1)?; + match front[0] { + 0 => Ok(false), + 1 => Ok(true), + v => Err(Error::InvalidBool(v)), + } + } +} + +impl Serialize for usize { + fn serialize_to(&self, serializer: &mut S) -> Result<()> { + (*self as u64).serialize_to(serializer) + } +} + +impl<'a> Deserialize<'a> for usize { + fn deserialize_from>(buf: &mut D) -> Result + where + Self: Sized, + { + u64::deserialize_from(buf).map(|v| v as usize) + } +} + +impl Serialize for isize { + fn serialize_to(&self, serializer: &mut S) -> Result<()> { + (*self as i64).serialize_to(serializer) + } +} + +impl<'a> Deserialize<'a> for isize { + fn deserialize_from>(buf: &mut D) -> Result + where + Self: Sized, + { + i64::deserialize_from(buf).map(|v| v as isize) + } +} + +impl Serialize for char { + fn serialize_to(&self, serializer: &mut S) -> Result<()> { + (*self as u32).serialize_to(serializer) + } +} + +impl<'a> Deserialize<'a> for char { + fn deserialize_from>(buf: &mut D) -> Result + where + Self: Sized, + { + let c = u32::deserialize_from(buf)?; + char::from_u32(c).ok_or(Error::InvalidChar(c)) + } +} + +impl Serialize for &T { + fn serialize_to(&self, serializer: &mut S) -> Result<()> { + T::serialize_to(self, serializer) + } +} + +impl Serialize for &mut T { + fn serialize_to(&self, serializer: &mut S) -> Result<()> { + T::serialize_to(self, serializer) + } +} + +impl Serialize for () { + fn serialize_to(&self, _: &mut S) -> Result<()> { + Ok(()) + } +} + +impl<'a> Deserialize<'a> for () { + fn deserialize_from>(_: &mut D) -> Result + where + Self: Sized, + { + Ok(()) + } +} + +impl Serialize for Option { + fn serialize_to(&self, serializer: &mut S) -> Result<()> { + if let Some(item) = self { + item.serialize_to(serializer)?; + true.serialize_to(serializer) + } else { + false.serialize_to(serializer) + } + } +} + +impl<'a, Item: Deserialize<'a>> Deserialize<'a> for Option { + fn deserialize_from>(buf: &mut D) -> Result + where + Self: Sized, + { + let has = bool::deserialize_from(buf)?; + if has { + Ok(Some(Item::deserialize_from(buf)?)) + } else { + Ok(None) + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_primitive_types() { + for ser in [u64::MIN, u64::MAX] { + let bytes = ser.serialize::().unwrap(); + assert_eq!(bytes.len(), 8); + + let der = u64::deserialize(&bytes[..]).unwrap(); + assert_eq!(ser, der); + } + + assert!(bool::deserialize(true.serialize::().unwrap().as_ref()).unwrap()); + assert!(!bool::deserialize(false.serialize::().unwrap().as_ref()).unwrap()); + assert!(!bool::deserialize(&[0][..]).unwrap()); + assert!(bool::deserialize(&[1][..]).unwrap()); + assert!(bool::deserialize(&[2][..]).is_err()); + assert!(bool::deserialize(&[][..]).is_err()); + assert_eq!( + bool::deserialize(&[][..]).unwrap_err().to_string(), + "data is short for deserialize: expect 1, actual 0".to_owned() + ); + + { + let ser = 233isize; + let bytes: DownwardBytes = ser.serialize().unwrap(); + let der = isize::deserialize(&bytes[..]).unwrap(); + assert_eq!(ser, der); + + isize::deserialize([0xff].as_slice()).unwrap_err(); + } + + { + let mut ser = '😊'; + let r = &mut ser; + let bytes: DownwardBytes = r.serialize().unwrap(); + let der = char::deserialize(&bytes[..]).unwrap(); + assert_eq!(ser, der); + + char::deserialize([0xff].as_slice()).unwrap_err(); + char::deserialize([0, 0, 0x11, 0].as_slice()).unwrap_err(); + } + + { + let ser = (); + let bytes = ser.serialize::().unwrap(); + assert!(bytes.is_empty()); + <()>::deserialize(&bytes[..]).unwrap(); + } + + { + assert!(u32::deserialize([0, 1, 2].as_ref()).is_err()); + } + } +} diff --git a/derse/src/impl/result.rs b/derse/src/impls/result.rs similarity index 100% rename from derse/src/impl/result.rs rename to derse/src/impls/result.rs diff --git a/derse/src/impl/socket_addr.rs b/derse/src/impls/socket_addr.rs similarity index 100% rename from derse/src/impl/socket_addr.rs rename to derse/src/impls/socket_addr.rs diff --git a/derse/src/impls/string.rs b/derse/src/impls/string.rs new file mode 100644 index 0000000..0c54e81 --- /dev/null +++ b/derse/src/impls/string.rs @@ -0,0 +1,146 @@ +use crate::*; +use std::borrow::Cow; + +impl Serialize for str { + fn serialize_to(&self, serializer: &mut S) -> Result<()> { + serializer.prepend(self.as_bytes())?; + VarInt64(self.len() as u64).serialize_to(serializer) + } +} + +impl<'a> Deserialize<'a> for &'a str { + fn deserialize_from>(buf: &mut D) -> Result + where + Self: Sized, + { + let len = VarInt64::deserialize_from(buf)?.0 as usize; + let front = buf.pop(len)?; + match front { + Cow::Borrowed(borrowed) => match std::str::from_utf8(borrowed) { + Ok(str) => Ok(str), + Err(_) => Err(Error::InvalidString(Vec::from(borrowed))), + }, + Cow::Owned(_) => Err(Error::InvalidString(Default::default())), + } + } +} + +impl Serialize for [u8] { + fn serialize_to(&self, serializer: &mut S) -> Result<()> { + serializer.prepend(self)?; + VarInt64(self.len() as u64).serialize_to(serializer) + } +} + +impl<'a> Deserialize<'a> for &'a [u8] { + fn deserialize_from>(buf: &mut D) -> Result + where + Self: Sized, + { + let len = VarInt64::deserialize_from(buf)?.0 as usize; + let front = buf.pop(len)?; + match front { + Cow::Borrowed(borrowed) => Ok(borrowed), + Cow::Owned(_) => Err(Error::InvalidString(Default::default())), + } + } +} + +impl Serialize for String { + fn serialize_to(&self, serializer: &mut S) -> Result<()> { + self.as_str().serialize_to(serializer) + } +} + +impl<'a> Deserialize<'a> for String { + fn deserialize_from>(buf: &mut D) -> Result + where + Self: Sized, + { + Ok(Cow::::deserialize_from(buf)?.into_owned()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_string() { + { + let ser = "hello world!"; + let bytes: DownwardBytes = ser.serialize().unwrap(); + let der: String = String::deserialize(&bytes[..]).unwrap(); + assert_eq!(ser, &der); + + let der = Cow::::deserialize(&bytes[..]).unwrap(); + assert_eq!(ser, &der); + + let der = Cow::<[u8]>::deserialize(&bytes[..]).unwrap(); + assert_eq!(ser.len(), der.len()); + let bytes: DownwardBytes = der.serialize().unwrap(); + + let der = Cow::::deserialize(&bytes[..]).unwrap(); + assert_eq!(ser, der.as_ref()); + let bytes: DownwardBytes = der.serialize().unwrap(); + + let der: &str = Deserialize::deserialize(&bytes[..]).unwrap(); + assert_eq!(ser, der); + + let bytes2: DownwardBytes = der.serialize().unwrap(); + assert_eq!(bytes, bytes2); + + assert!(Cow::::deserialize([2, 0xC0, 0xAF].as_slice()).is_err()); + assert!(Cow::::deserialize([128].as_slice()).is_err()); + + let result: Result<&str> = Deserialize::deserialize([2, 0xC0, 0xAF].as_slice()); + assert!(result.is_err()); + } + + { + let ser = "hello world!".to_string(); + let bytes: DownwardBytes = ser.serialize().unwrap(); + let der: String = String::deserialize(&bytes[..]).unwrap(); + assert_eq!(ser, der); + + assert!(String::deserialize(&bytes[..1]).is_err()); + assert!(String::deserialize(&bytes[..5]).is_err()); + } + + { + let ser = (String::from("hello"), 64u32); + let bytes: DownwardBytes = ser.serialize().unwrap(); + assert_eq!(bytes.len(), 1 + 5 + 4); + let der: (String, u32) = Deserialize::deserialize(&bytes[..]).unwrap(); + assert_eq!(ser, der); + + let der: (String, u16, u16) = Deserialize::deserialize(&bytes[..]).unwrap(); + assert_eq!(ser.0, der.0); + assert_eq!(ser.1, der.1 as _); + assert_eq!(0, der.2); + } + + { + let msg = "0".repeat(47) + "A"; + let a = msg[..25].as_bytes(); + let b = msg[24..].as_bytes(); + let c = [a, b]; + + let der = String::deserialize(BytesArray::new(&c)).unwrap(); + assert_eq!(msg, der); + + let der = Cow::::deserialize(BytesArray::new(&c)).unwrap(); + assert_eq!(msg, der); + + let result: Result<&str> = Deserialize::deserialize(BytesArray::new(&c)); + assert!(result.is_err()); + + assert!(String::deserialize(BytesArray::new(&c[1..])).is_err()); + + let a = [0x2, 0xC0]; + let b = [0xAF]; + assert!(<&[u8]>::deserialize(BytesArray::new(&[&a[..], &b[..]])).is_err()); + assert!(Cow::::deserialize(BytesArray::new(&[&a[..], &b[..]])).is_err()); + } + } +} diff --git a/derse/src/impl/tinyvec.rs b/derse/src/impls/tinyvec.rs similarity index 100% rename from derse/src/impl/tinyvec.rs rename to derse/src/impls/tinyvec.rs diff --git a/derse/src/impl/tuple.rs b/derse/src/impls/tuple.rs similarity index 100% rename from derse/src/impl/tuple.rs rename to derse/src/impls/tuple.rs diff --git a/derse/src/lib.rs b/derse/src/lib.rs index e37aa54..0fd2d4d 100644 --- a/derse/src/lib.rs +++ b/derse/src/lib.rs @@ -2,8 +2,7 @@ mod bytes_array; mod deserializer; mod downward_bytes; mod error; -mod r#impl; -mod serialization; +mod impls; mod serializer; mod varint64; diff --git a/derse/src/serialization.rs b/derse/src/serialization.rs deleted file mode 100644 index 21db51c..0000000 --- a/derse/src/serialization.rs +++ /dev/null @@ -1,412 +0,0 @@ -use crate::*; -use std::borrow::Cow; - -macro_rules! impl_serialize_trait { - ($($t:ty),*) => { - $(impl Serialize for $t { - fn serialize_to(&self, serializer: &mut S) -> Result<()> { - serializer.prepend(&self.to_le_bytes()) - } - } - - impl<'a> Deserialize<'a> for $t { - fn deserialize_from>(buf: &mut D) -> Result - where - Self: Sized, - { - let front = buf.pop(std::mem::size_of::())?; - Ok(Self::from_le_bytes(front.as_ref().try_into().unwrap())) - } - })* - }; -} - -impl_serialize_trait! {i8, i16, i32, i64, i128, u8, u16, u32, u64, u128, f32, f64} - -impl Serialize for bool { - fn serialize_to(&self, serializer: &mut S) -> Result<()> { - serializer.prepend([*self as u8]) - } -} - -impl<'a> Deserialize<'a> for bool { - fn deserialize_from>(buf: &mut D) -> Result - where - Self: Sized, - { - let front = buf.pop(1)?; - match front[0] { - 0 => Ok(false), - 1 => Ok(true), - v => Err(Error::InvalidBool(v)), - } - } -} - -impl Serialize for usize { - fn serialize_to(&self, serializer: &mut S) -> Result<()> { - (*self as u64).serialize_to(serializer) - } -} - -impl<'a> Deserialize<'a> for usize { - fn deserialize_from>(buf: &mut D) -> Result - where - Self: Sized, - { - u64::deserialize_from(buf).map(|v| v as usize) - } -} - -impl Serialize for isize { - fn serialize_to(&self, serializer: &mut S) -> Result<()> { - (*self as i64).serialize_to(serializer) - } -} - -impl<'a> Deserialize<'a> for isize { - fn deserialize_from>(buf: &mut D) -> Result - where - Self: Sized, - { - i64::deserialize_from(buf).map(|v| v as isize) - } -} - -impl Serialize for char { - fn serialize_to(&self, serializer: &mut S) -> Result<()> { - (*self as u32).serialize_to(serializer) - } -} - -impl<'a> Deserialize<'a> for char { - fn deserialize_from>(buf: &mut D) -> Result - where - Self: Sized, - { - let c = u32::deserialize_from(buf)?; - char::from_u32(c).ok_or(Error::InvalidChar(c)) - } -} - -impl Serialize for str { - fn serialize_to(&self, serializer: &mut S) -> Result<()> { - serializer.prepend(self.as_bytes())?; - VarInt64(self.len() as u64).serialize_to(serializer) - } -} - -impl<'a> Deserialize<'a> for &'a str { - fn deserialize_from>(buf: &mut D) -> Result - where - Self: Sized, - { - let len = VarInt64::deserialize_from(buf)?.0 as usize; - let front = buf.pop(len)?; - match front { - Cow::Borrowed(borrowed) => match std::str::from_utf8(borrowed) { - Ok(str) => Ok(str), - Err(_) => Err(Error::InvalidString(Vec::from(borrowed))), - }, - Cow::Owned(_) => Err(Error::InvalidString(Default::default())), - } - } -} - -impl Serialize for [u8] { - fn serialize_to(&self, serializer: &mut S) -> Result<()> { - serializer.prepend(self)?; - VarInt64(self.len() as u64).serialize_to(serializer) - } -} - -impl<'a> Deserialize<'a> for &'a [u8] { - fn deserialize_from>(buf: &mut D) -> Result - where - Self: Sized, - { - let len = VarInt64::deserialize_from(buf)?.0 as usize; - let front = buf.pop(len)?; - match front { - Cow::Borrowed(borrowed) => Ok(borrowed), - Cow::Owned(_) => Err(Error::InvalidString(Default::default())), - } - } -} - -impl Serialize for [u8; N] { - fn serialize_to(&self, serializer: &mut S) -> Result<()> { - serializer.prepend(self) - } -} - -impl<'a, const N: usize> Deserialize<'a> for [u8; N] { - fn deserialize_from>(buf: &mut D) -> Result - where - Self: Sized, - { - let front = buf.pop(N)?; - let mut ret = [0u8; N]; - ret.copy_from_slice(&front); - Ok(ret) - } -} - -impl Serialize for Cow<'_, [u8]> { - fn serialize_to(&self, serializer: &mut S) -> Result<()> { - <[u8]>::serialize_to(self, serializer) - } -} - -impl<'a> Deserialize<'a> for Cow<'a, [u8]> { - fn deserialize_from>(buf: &mut D) -> Result - where - Self: Sized, - { - let len = VarInt64::deserialize_from(buf)?.0 as usize; - buf.pop(len) - } -} - -impl Serialize for Cow<'_, str> { - fn serialize_to(&self, serializer: &mut S) -> Result<()> { - self.as_ref().serialize_to(serializer) - } -} - -impl<'a> Deserialize<'a> for Cow<'a, str> { - fn deserialize_from>(buf: &mut D) -> Result - where - Self: Sized, - { - let len = VarInt64::deserialize_from(buf)?.0 as usize; - let front = buf.pop(len)?; - match front { - Cow::Borrowed(borrowed) => match std::str::from_utf8(borrowed) { - Ok(str) => Ok(Cow::Borrowed(str)), - Err(_) => Err(Error::InvalidString(Vec::from(borrowed))), - }, - Cow::Owned(owned) => match String::from_utf8(owned) { - Ok(str) => Ok(Cow::Owned(str)), - Err(e) => Err(Error::InvalidString(e.into_bytes())), - }, - } - } -} - -impl + Serialize> Serialize for Cow<'_, T> { - fn serialize_to(&self, serializer: &mut S) -> Result<()> { - self.as_ref().serialize_to(serializer) - } -} - -impl<'a, T: ToOwned + Deserialize<'a>> Deserialize<'a> for Cow<'a, T> { - fn deserialize_from>(buf: &mut D) -> Result - where - Self: Sized, - { - Ok(Cow::Owned(T::deserialize_from(buf)?)) - } -} - -impl Serialize for String { - fn serialize_to(&self, serializer: &mut S) -> Result<()> { - self.as_str().serialize_to(serializer) - } -} - -impl<'a> Deserialize<'a> for String { - fn deserialize_from>(buf: &mut D) -> Result - where - Self: Sized, - { - Ok(Cow::::deserialize_from(buf)?.into_owned()) - } -} - -impl Serialize for Option { - fn serialize_to(&self, serializer: &mut S) -> Result<()> { - if let Some(item) = self { - item.serialize_to(serializer)?; - true.serialize_to(serializer) - } else { - false.serialize_to(serializer) - } - } -} - -impl<'a, Item: Deserialize<'a>> Deserialize<'a> for Option { - fn deserialize_from>(buf: &mut D) -> Result - where - Self: Sized, - { - let has = bool::deserialize_from(buf)?; - if has { - Ok(Some(Item::deserialize_from(buf)?)) - } else { - Ok(None) - } - } -} - -impl Serialize for &T { - fn serialize_to(&self, serializer: &mut S) -> Result<()> { - T::serialize_to(self, serializer) - } -} - -impl Serialize for () { - fn serialize_to(&self, _: &mut S) -> Result<()> { - Ok(()) - } -} - -impl<'a> Deserialize<'a> for () { - fn deserialize_from>(_: &mut D) -> Result - where - Self: Sized, - { - Ok(()) - } -} - -#[cfg(test)] -mod tests { - use super::super::*; - use super::*; - - #[test] - fn test_serialization() { - for ser in [u64::MIN, u64::MAX] { - let bytes = ser.serialize::().unwrap(); - assert_eq!(bytes.len(), 8); - - let der = u64::deserialize(&bytes[..]).unwrap(); - assert_eq!(ser, der); - } - - assert!(bool::deserialize(true.serialize::().unwrap().as_ref()).unwrap()); - assert!(!bool::deserialize(false.serialize::().unwrap().as_ref()).unwrap()); - assert!(!bool::deserialize(&[0][..]).unwrap()); - assert!(bool::deserialize(&[1][..]).unwrap()); - assert!(bool::deserialize(&[2][..]).is_err()); - assert!(bool::deserialize(&[][..]).is_err()); - assert_eq!( - bool::deserialize(&[][..]).unwrap_err().to_string(), - "data is short for deserialize: expect 1, actual 0".to_owned() - ); - - { - let ser = 233isize; - let bytes: DownwardBytes = ser.serialize().unwrap(); - let der = isize::deserialize(&bytes[..]).unwrap(); - assert_eq!(ser, der); - - isize::deserialize([0xff].as_slice()).unwrap_err(); - } - - { - let ser = '😊'; - let bytes: DownwardBytes = ser.serialize().unwrap(); - let der = char::deserialize(&bytes[..]).unwrap(); - assert_eq!(ser, der); - - char::deserialize([0xff].as_slice()).unwrap_err(); - char::deserialize([0, 0, 0x11, 0].as_slice()).unwrap_err(); - } - - { - let ser = "hello world!"; - let bytes: DownwardBytes = ser.serialize().unwrap(); - let der: String = String::deserialize(&bytes[..]).unwrap(); - assert_eq!(ser, &der); - - let der = Cow::::deserialize(&bytes[..]).unwrap(); - assert_eq!(ser, &der); - - let der = Cow::<[u8]>::deserialize(&bytes[..]).unwrap(); - assert_eq!(ser.len(), der.len()); - let bytes: DownwardBytes = der.serialize().unwrap(); - - let der = Cow::::deserialize(&bytes[..]).unwrap(); - assert_eq!(ser, der.as_ref()); - let bytes: DownwardBytes = der.serialize().unwrap(); - - let der: &str = Deserialize::deserialize(&bytes[..]).unwrap(); - assert_eq!(ser, der); - - let bytes2: DownwardBytes = der.serialize().unwrap(); - assert_eq!(bytes, bytes2); - - assert!(Cow::::deserialize([2, 0xC0, 0xAF].as_slice()).is_err()); - assert!(Cow::::deserialize([128].as_slice()).is_err()); - - let result: Result<&str> = Deserialize::deserialize([2, 0xC0, 0xAF].as_slice()); - assert!(result.is_err()); - } - - { - let ser = "hello world!".to_string(); - let bytes: DownwardBytes = ser.serialize().unwrap(); - let der: String = String::deserialize(&bytes[..]).unwrap(); - assert_eq!(ser, der); - - assert!(String::deserialize(&bytes[..1]).is_err()); - assert!(String::deserialize(&bytes[..5]).is_err()); - } - - { - assert!(u32::deserialize([0, 1, 2].as_ref()).is_err()); - } - - { - let ser = (String::from("hello"), 64u32); - let bytes: DownwardBytes = ser.serialize().unwrap(); - assert_eq!(bytes.len(), 1 + 5 + 4); - let der: (String, u32) = Deserialize::deserialize(&bytes[..]).unwrap(); - assert_eq!(ser, der); - - let der: (String, u16, u16) = Deserialize::deserialize(&bytes[..]).unwrap(); - assert_eq!(ser.0, der.0); - assert_eq!(ser.1, der.1 as _); - assert_eq!(0, der.2); - } - - { - let msg = "0".repeat(47) + "A"; - let a = msg[..25].as_bytes(); - let b = msg[24..].as_bytes(); - let c = [a, b]; - - let der = String::deserialize(BytesArray::new(&c)).unwrap(); - assert_eq!(msg, der); - - let der = Cow::::deserialize(BytesArray::new(&c)).unwrap(); - assert_eq!(msg, der); - - let result: Result<&str> = Deserialize::deserialize(BytesArray::new(&c)); - assert!(result.is_err()); - - assert!(String::deserialize(BytesArray::new(&c[1..])).is_err()); - - let a = [0x2, 0xC0]; - let b = [0xAF]; - assert!(Cow::::deserialize(BytesArray::new(&[&a[..], &b[..]])).is_err()); - } - - { - let ser = (); - let bytes = ser.serialize::().unwrap(); - assert!(bytes.is_empty()); - <()>::deserialize(&bytes[..]).unwrap(); - } - - { - let ser = 233u32; - let bytes = ser.serialize::().unwrap(); - let array = <[u8; 4]>::deserialize(&bytes[..]).unwrap(); - let der = u32::from_le_bytes(array); - assert_eq!(ser, der); - } - } -}