From 7a45d2649b08f4ecf2a8a756be860a05e0545888 Mon Sep 17 00:00:00 2001 From: Zakarum Date: Thu, 16 May 2024 21:56:58 +0200 Subject: [PATCH] Support serializing Box,Rc and Arc Formula is not implemented for pointers, so user have to make separate formula type --- benchmark/Cargo.toml | 2 +- examples/test.rs | 1 + proc/src/attrs.rs | 1 + src/boxed.rs | 193 +++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 3 + src/primitive.rs | 75 ++++++++++------- 6 files changed, 244 insertions(+), 31 deletions(-) create mode 100644 src/boxed.rs diff --git a/benchmark/Cargo.toml b/benchmark/Cargo.toml index 2b055fb..3ec68d4 100644 --- a/benchmark/Cargo.toml +++ b/benchmark/Cargo.toml @@ -11,7 +11,7 @@ default = ["alkahest/default", "speedy", "rkyv", "serde", "bincode"] [dependencies] alkahest = { path = "..", features = ["derive"], default-features = false } -criterion = { version = "0.4" } +criterion = { version = "0.5" } serde = { version = "1.0", features = ["derive"], optional = true } serde_json = { version = "1.0", optional = true } bincode = { version = "1.3", optional = true } diff --git a/examples/test.rs b/examples/test.rs index acdaed9..3b056a9 100644 --- a/examples/test.rs +++ b/examples/test.rs @@ -1,4 +1,5 @@ #![deny(warnings)] +#![allow(clippy::disallowed_names)] use alkahest::*; diff --git a/proc/src/attrs.rs b/proc/src/attrs.rs index 5c159e5..47b5054 100644 --- a/proc/src/attrs.rs +++ b/proc/src/attrs.rs @@ -37,6 +37,7 @@ proc_easy::easy_parse! { } proc_easy::easy_parse! { + #[allow(unused)] enum ImplTrait { Formula(Formula), Serialize(Serialize, proc_easy::EasyMaybe), diff --git a/src/boxed.rs b/src/boxed.rs new file mode 100644 index 0000000..d99a16d --- /dev/null +++ b/src/boxed.rs @@ -0,0 +1,193 @@ +use alloc::{boxed::Box, rc::Rc, sync::Arc}; + +use crate::{ + buffer::Buffer, + deserialize::{Deserialize, DeserializeError, Deserializer}, + formula::BareFormula, + serialize::{Serialize, Sizes}, + SerializeRef, +}; + +impl Serialize for Box +where + F: BareFormula, + T: Serialize, +{ + #[inline(always)] + fn serialize(self, sizes: &mut Sizes, buffer: B) -> Result<(), B::Error> + where + B: Buffer, + { + >::serialize(*self, sizes, buffer) + } + + #[inline(always)] + fn size_hint(&self) -> Option { + >::size_hint(self) + } +} + +impl SerializeRef for Box +where + F: BareFormula, + T: SerializeRef, +{ + #[inline(always)] + fn serialize(&self, sizes: &mut Sizes, buffer: B) -> Result<(), B::Error> + where + B: Buffer, + { + >::serialize(self.as_ref(), sizes, buffer) + } + + #[inline(always)] + fn size_hint(&self) -> Option { + >::size_hint(self.as_ref()) + } +} + +impl<'de, T, F> Deserialize<'de, F> for Box +where + F: BareFormula, + T: Deserialize<'de, F>, +{ + #[inline(always)] + fn deserialize(deserializer: Deserializer<'de>) -> Result + where + Self: Sized, + { + Ok(Box::new(>::deserialize(deserializer)?)) + } + + #[inline(always)] + fn deserialize_in_place( + &mut self, + deserializer: Deserializer<'de>, + ) -> Result<(), DeserializeError> { + >::deserialize_in_place(self, deserializer) + } +} + +impl Serialize for Rc +where + F: BareFormula, + T: SerializeRef, +{ + #[inline(always)] + fn serialize(self, sizes: &mut Sizes, buffer: B) -> Result<(), B::Error> + where + B: Buffer, + { + >::serialize(self.as_ref(), sizes, buffer) + } + + #[inline(always)] + fn size_hint(&self) -> Option { + >::size_hint(self.as_ref()) + } +} + +impl SerializeRef for Rc +where + F: BareFormula, + T: SerializeRef, +{ + #[inline(always)] + fn serialize(&self, sizes: &mut Sizes, buffer: B) -> Result<(), B::Error> + where + B: Buffer, + { + >::serialize(self.as_ref(), sizes, buffer) + } + + #[inline(always)] + fn size_hint(&self) -> Option { + >::size_hint(self.as_ref()) + } +} + +impl<'de, T, F> Deserialize<'de, F> for Rc +where + F: BareFormula, + T: Deserialize<'de, F>, +{ + #[inline(always)] + fn deserialize(deserializer: Deserializer<'de>) -> Result + where + Self: Sized, + { + Ok(Rc::new(>::deserialize(deserializer)?)) + } + + #[inline(always)] + fn deserialize_in_place( + &mut self, + deserializer: Deserializer<'de>, + ) -> Result<(), DeserializeError> { + *self = Rc::new(>::deserialize(deserializer)?); + + Ok(()) + } +} + +impl Serialize for Arc +where + F: BareFormula, + T: SerializeRef, +{ + #[inline(always)] + fn serialize(self, sizes: &mut Sizes, buffer: B) -> Result<(), B::Error> + where + B: Buffer, + { + >::serialize(self.as_ref(), sizes, buffer) + } + + #[inline(always)] + fn size_hint(&self) -> Option { + >::size_hint(self.as_ref()) + } +} + +impl SerializeRef for Arc +where + F: BareFormula, + T: SerializeRef, +{ + #[inline(always)] + fn serialize(&self, sizes: &mut Sizes, buffer: B) -> Result<(), B::Error> + where + B: Buffer, + { + >::serialize(self.as_ref(), sizes, buffer) + } + + #[inline(always)] + fn size_hint(&self) -> Option { + >::size_hint(self.as_ref()) + } +} + +impl<'de, T, F> Deserialize<'de, F> for Arc +where + F: BareFormula, + T: Deserialize<'de, F>, +{ + #[inline(always)] + fn deserialize(deserializer: Deserializer<'de>) -> Result + where + Self: Sized, + { + Ok(Arc::new(>::deserialize(deserializer)?)) + } + + #[inline(always)] + fn deserialize_in_place( + &mut self, + deserializer: Deserializer<'de>, + ) -> Result<(), DeserializeError> { + *self = Arc::new(>::deserialize(deserializer)?); + + Ok(()) + } +} diff --git a/src/lib.rs b/src/lib.rs index 02241b2..aab10d7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -43,6 +43,9 @@ mod str; mod tuple; mod vlq; +#[cfg(feature = "alloc")] +mod boxed; + #[cfg(test)] mod tests; diff --git a/src/primitive.rs b/src/primitive.rs index a97f86b..2488123 100644 --- a/src/primitive.rs +++ b/src/primitive.rs @@ -11,14 +11,14 @@ macro_rules! impl_primitive { () => {}; ([$($head:ident)+] $([$($tail:ident)+])*) => { - impl_primitive!(@ < $($head)+); + impl_primitive!(^ < $($head)+); impl_primitive!($([$($tail)+])*); }; - (@ $($head:ident)* <) => {}; - (@ $($head:ident)* < $cursor:ident $($tail:ident)*) => { + (^ $($head:ident)* <) => {}; + (^ $($head:ident)* < $cursor:ident $($tail:ident)*) => { impl_primitive!{! $($head)* < $cursor < $($tail)* } - impl_primitive!{@ $($head)* $cursor < $($tail)* } + impl_primitive!{^ $($head)* $cursor < $($tail)* } }; (! $($from:ident)* < $ty:ident < $($to:ident)*) => { @@ -77,6 +77,26 @@ macro_rules! impl_primitive { } } + impl Deserialize<'_, $ty> for $ty + { + #[inline(always)] + fn deserialize(mut de: Deserializer) -> Result { + let input = de.read_byte_array::<{size_of::<$ty>()}>()?; + // de.finish()?; + let value = <$ty>::from_le_bytes(input); + return Ok(value); + } + + #[inline(always)] + fn deserialize_in_place(&mut self, mut de: Deserializer) -> Result<(), DeserializeError> { + let input = de.read_byte_array::<{size_of::<$ty>()}>()?; + // de.finish()?; + let value = <$ty>::from_le_bytes(input); + *self = value; + Ok(()) + } + } + $( impl SerializeRef<$ty> for $from { #[inline(always)] @@ -92,29 +112,27 @@ macro_rules! impl_primitive { Some(Sizes{ heap: 0, stack: size_of::<$ty>()}) } } - )* - impl Deserialize<'_, $ty> for T - where - T: From<$ty>, - { - #[inline(always)] - fn deserialize(mut de: Deserializer) -> Result { - let input = de.read_byte_array::<{size_of::<$ty>()}>()?; - // de.finish()?; - let value = <$ty>::from_le_bytes(input); - return Ok(From::from(value)); - } + impl Deserialize<'_, $from> for $ty + { + #[inline(always)] + fn deserialize(mut de: Deserializer) -> Result { + let input = de.read_byte_array::<{size_of::<$from>()}>()?; + // de.finish()?; + let value = <$from>::from_le_bytes(input); + return Ok($ty::from(value)); + } - #[inline(always)] - fn deserialize_in_place(&mut self, mut de: Deserializer) -> Result<(), DeserializeError> { - let input = de.read_byte_array::<{size_of::<$ty>()}>()?; - // de.finish()?; - let value = <$ty>::from_le_bytes(input); - *self = From::from(value); - Ok(()) + #[inline(always)] + fn deserialize_in_place(&mut self, mut de: Deserializer) -> Result<(), DeserializeError> { + let input = de.read_byte_array::<{size_of::<$from>()}>()?; + // de.finish()?; + let value = <$from>::from_le_bytes(input); + *self = $ty::from(value); + Ok(()) + } } - } + )* }; } @@ -169,20 +187,17 @@ impl Serialize for &bool { } } -impl Deserialize<'_, bool> for T -where - T: From, -{ +impl Deserialize<'_, bool> for bool { #[inline(always)] fn deserialize(mut de: Deserializer) -> Result { let byte = de.read_byte()?; - Ok(T::from(byte != 0)) + Ok(byte != 0) } #[inline(always)] fn deserialize_in_place(&mut self, mut de: Deserializer) -> Result<(), DeserializeError> { let byte = de.read_byte()?; - *self = From::from(byte != 0); + *self = byte != 0; Ok(()) } }