Skip to content

Commit

Permalink
Support serializing Box,Rc and Arc
Browse files Browse the repository at this point in the history
Formula is not implemented for pointers,
so user have to make separate formula type
  • Loading branch information
zakarumych committed May 16, 2024
1 parent 99a5b68 commit 7a45d26
Show file tree
Hide file tree
Showing 6 changed files with 244 additions and 31 deletions.
2 changes: 1 addition & 1 deletion benchmark/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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 }
Expand Down
1 change: 1 addition & 0 deletions examples/test.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#![deny(warnings)]
#![allow(clippy::disallowed_names)]

use alkahest::*;

Expand Down
1 change: 1 addition & 0 deletions proc/src/attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ proc_easy::easy_parse! {
}

proc_easy::easy_parse! {
#[allow(unused)]
enum ImplTrait {
Formula(Formula),
Serialize(Serialize, proc_easy::EasyMaybe<SerializeParams>),
Expand Down
193 changes: 193 additions & 0 deletions src/boxed.rs
Original file line number Diff line number Diff line change
@@ -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<T, F> Serialize<F> for Box<T>
where
F: BareFormula,
T: Serialize<F>,
{
#[inline(always)]
fn serialize<B>(self, sizes: &mut Sizes, buffer: B) -> Result<(), B::Error>
where
B: Buffer,
{
<T as Serialize<F>>::serialize(*self, sizes, buffer)
}

#[inline(always)]
fn size_hint(&self) -> Option<Sizes> {
<T as Serialize<F>>::size_hint(self)
}
}

impl<T, F> SerializeRef<F> for Box<T>
where
F: BareFormula,
T: SerializeRef<F>,
{
#[inline(always)]
fn serialize<B>(&self, sizes: &mut Sizes, buffer: B) -> Result<(), B::Error>
where
B: Buffer,
{
<T as SerializeRef<F>>::serialize(self.as_ref(), sizes, buffer)
}

#[inline(always)]
fn size_hint(&self) -> Option<Sizes> {
<T as SerializeRef<F>>::size_hint(self.as_ref())
}
}

impl<'de, T, F> Deserialize<'de, F> for Box<T>
where
F: BareFormula,
T: Deserialize<'de, F>,
{
#[inline(always)]
fn deserialize(deserializer: Deserializer<'de>) -> Result<Self, DeserializeError>
where
Self: Sized,
{
Ok(Box::new(<T as Deserialize<F>>::deserialize(deserializer)?))
}

#[inline(always)]
fn deserialize_in_place(
&mut self,
deserializer: Deserializer<'de>,
) -> Result<(), DeserializeError> {
<T as Deserialize<F>>::deserialize_in_place(self, deserializer)
}
}

impl<T, F> Serialize<F> for Rc<T>
where
F: BareFormula,
T: SerializeRef<F>,
{
#[inline(always)]
fn serialize<B>(self, sizes: &mut Sizes, buffer: B) -> Result<(), B::Error>
where
B: Buffer,
{
<T as SerializeRef<F>>::serialize(self.as_ref(), sizes, buffer)
}

#[inline(always)]
fn size_hint(&self) -> Option<Sizes> {
<T as SerializeRef<F>>::size_hint(self.as_ref())
}
}

impl<T, F> SerializeRef<F> for Rc<T>
where
F: BareFormula,
T: SerializeRef<F>,
{
#[inline(always)]
fn serialize<B>(&self, sizes: &mut Sizes, buffer: B) -> Result<(), B::Error>
where
B: Buffer,
{
<T as SerializeRef<F>>::serialize(self.as_ref(), sizes, buffer)
}

#[inline(always)]
fn size_hint(&self) -> Option<Sizes> {
<T as SerializeRef<F>>::size_hint(self.as_ref())
}
}

impl<'de, T, F> Deserialize<'de, F> for Rc<T>
where
F: BareFormula,
T: Deserialize<'de, F>,
{
#[inline(always)]
fn deserialize(deserializer: Deserializer<'de>) -> Result<Self, DeserializeError>
where
Self: Sized,
{
Ok(Rc::new(<T as Deserialize<F>>::deserialize(deserializer)?))
}

#[inline(always)]
fn deserialize_in_place(
&mut self,
deserializer: Deserializer<'de>,
) -> Result<(), DeserializeError> {
*self = Rc::new(<T as Deserialize<F>>::deserialize(deserializer)?);

Ok(())
}
}

impl<T, F> Serialize<F> for Arc<T>
where
F: BareFormula,
T: SerializeRef<F>,
{
#[inline(always)]
fn serialize<B>(self, sizes: &mut Sizes, buffer: B) -> Result<(), B::Error>
where
B: Buffer,
{
<T as SerializeRef<F>>::serialize(self.as_ref(), sizes, buffer)
}

#[inline(always)]
fn size_hint(&self) -> Option<Sizes> {
<T as SerializeRef<F>>::size_hint(self.as_ref())
}
}

impl<T, F> SerializeRef<F> for Arc<T>
where
F: BareFormula,
T: SerializeRef<F>,
{
#[inline(always)]
fn serialize<B>(&self, sizes: &mut Sizes, buffer: B) -> Result<(), B::Error>
where
B: Buffer,
{
<T as SerializeRef<F>>::serialize(self.as_ref(), sizes, buffer)
}

#[inline(always)]
fn size_hint(&self) -> Option<Sizes> {
<T as SerializeRef<F>>::size_hint(self.as_ref())
}
}

impl<'de, T, F> Deserialize<'de, F> for Arc<T>
where
F: BareFormula,
T: Deserialize<'de, F>,
{
#[inline(always)]
fn deserialize(deserializer: Deserializer<'de>) -> Result<Self, DeserializeError>
where
Self: Sized,
{
Ok(Arc::new(<T as Deserialize<F>>::deserialize(deserializer)?))
}

#[inline(always)]
fn deserialize_in_place(
&mut self,
deserializer: Deserializer<'de>,
) -> Result<(), DeserializeError> {
*self = Arc::new(<T as Deserialize<F>>::deserialize(deserializer)?);

Ok(())
}
}
3 changes: 3 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ mod str;
mod tuple;
mod vlq;

#[cfg(feature = "alloc")]
mod boxed;

#[cfg(test)]
mod tests;

Expand Down
75 changes: 45 additions & 30 deletions src/primitive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)*) => {
Expand Down Expand Up @@ -77,6 +77,26 @@ macro_rules! impl_primitive {
}
}

impl Deserialize<'_, $ty> for $ty
{
#[inline(always)]
fn deserialize(mut de: Deserializer) -> Result<Self, DeserializeError> {
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)]
Expand All @@ -92,29 +112,27 @@ macro_rules! impl_primitive {
Some(Sizes{ heap: 0, stack: size_of::<$ty>()})
}
}
)*

impl<T> Deserialize<'_, $ty> for T
where
T: From<$ty>,
{
#[inline(always)]
fn deserialize(mut de: Deserializer) -> Result<Self, DeserializeError> {
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<Self, DeserializeError> {
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(())
}
}
}
)*
};
}

Expand Down Expand Up @@ -169,20 +187,17 @@ impl Serialize<bool> for &bool {
}
}

impl<T> Deserialize<'_, bool> for T
where
T: From<bool>,
{
impl Deserialize<'_, bool> for bool {
#[inline(always)]
fn deserialize(mut de: Deserializer) -> Result<Self, DeserializeError> {
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(())
}
}

0 comments on commit 7a45d26

Please sign in to comment.