From c08e769b8200eaabcbfde31f934a0ff6d1a4f1bc Mon Sep 17 00:00:00 2001 From: timofey Date: Sat, 22 Apr 2023 20:54:30 +0000 Subject: [PATCH] AtomicObject + StaticPair --- src/std/atomic.rs | 56 +------------ src/std/atomic/atomic_object.rs | 100 ++++++++++++++++++++++++ src/std/collections.rs | 1 + src/std/collections/pair.rs | 93 ++++++++++++++++++++++ src/std/collections/stack.rs | 20 ++--- src/std/inlining.rs | 3 +- src/std/inlining/static_pair.rs | 134 ++++++++++++++++++++++++++++++++ src/std/inlining/staticpair.rs | 1 - 8 files changed, 342 insertions(+), 66 deletions(-) create mode 100644 src/std/atomic/atomic_object.rs create mode 100644 src/std/collections/pair.rs create mode 100644 src/std/inlining/static_pair.rs delete mode 100644 src/std/inlining/staticpair.rs diff --git a/src/std/atomic.rs b/src/std/atomic.rs index 4beeb73..bc56b7c 100644 --- a/src/std/atomic.rs +++ b/src/std/atomic.rs @@ -1,6 +1,7 @@ //! This module allows to describe a primitive subset of [Mentionable] types, [Atomic]s, //! simple static types, which are completely [Context]-independent. +pub mod atomic_object; pub mod plain; use std::marker::PhantomData; @@ -19,55 +20,6 @@ pub trait Atomic: 'static + Sized + Clone + Serializable { fn unexpected_tail(tail: &[u8]) -> Self::ParseError; } -/// Generic implementation of a factory for [Atomic]s. -pub struct AtomicFactory(PhantomData); - -impl AtomicFactory { - fn new() -> Self { - AtomicFactory(PhantomData) - } -} - -impl Clone for AtomicFactory { - fn clone(&self) -> Self { - Self::new() - } -} - -impl<'a, Ctx: 'a + Context, A: Atomic> Mentionable<'a, Ctx> for A { - type Fctr = AtomicFactory; - - fn factory(&self) -> Self::Fctr { - AtomicFactory::new() - } - - fn topology(&self) -> Hash { - Ctx::hash(b"") - } - - fn points(&self) -> Vec>> { - vec![] - } -} - -impl<'a, Ctx: 'a + Context, A: Atomic> Factory<'a, Ctx> for AtomicFactory { - type Mtbl = A; - - type ParseError = A::ParseError; - - fn deserialize( - &self, - deserializer: &mut dyn Deserializer, - _resolver: Rc>, - ) -> ParseResult<'a, Ctx, Self> { - A::deserialize(deserializer) - } - - fn unexpected_tail(&self, tail: &[u8]) -> Self::ParseError { - A::unexpected_tail(tail) - } -} - fn _parse_slice(slice: &[u8]) -> Result { let mut deserializer = SliceDeserializer::from(slice); let mentionable = A::deserialize(&mut deserializer)?; @@ -81,17 +33,11 @@ fn _parse_slice(slice: &[u8]) -> Result { /// Extension trait to provide method-like utilities associated with [Atomic]s. pub trait ExtAtomic: Atomic { - /// Short-hand for getting specific [`AtomicFactory`]. - fn f() -> AtomicFactory; /// Static equivalent of [`ExtFactory::parse_slice`]. fn parse_slice(slice: &[u8]) -> Result; } impl ExtAtomic for A { - fn f() -> AtomicFactory { - AtomicFactory::new() - } - fn parse_slice(slice: &[u8]) -> Result { _parse_slice(slice) } diff --git a/src/std/atomic/atomic_object.rs b/src/std/atomic/atomic_object.rs new file mode 100644 index 0000000..8d564a6 --- /dev/null +++ b/src/std/atomic/atomic_object.rs @@ -0,0 +1,100 @@ +use std::ops::Deref; + +use super::*; + +pub struct AtomicObject { + atomic: A, +} + +impl From for AtomicObject { + fn from(value: A) -> Self { + Self { atomic: value } + } +} + +impl AsRef for AtomicObject { + fn as_ref(&self) -> &A { + &self.atomic + } +} + +impl Deref for AtomicObject { + type Target = A; + + fn deref(&self) -> &Self::Target { + &self.atomic + } +} + +impl Serializable for AtomicObject { + fn serialize(&self, serializer: &mut dyn Serializer) { + self.atomic.serialize(serializer) + } +} + +impl<'a, Ctx: 'a + Context, A: Atomic> Mentionable<'a, Ctx> for AtomicObject { + type Fctr = AtomicFactory; + + fn factory(&self) -> Self::Fctr { + AtomicFactory::new() + } + + fn topology(&self) -> Hash { + Ctx::hash(b"") + } + + fn points(&self) -> Vec>> { + vec![] + } +} + +/// Generic implementation of a factory for [Atomic]s. +pub struct AtomicFactory(PhantomData); + +impl AtomicFactory { + fn new() -> Self { + AtomicFactory(PhantomData) + } +} + +impl Clone for AtomicFactory { + fn clone(&self) -> Self { + Self::new() + } +} + +impl<'a, Ctx: 'a + Context, A: Atomic> Factory<'a, Ctx> for AtomicFactory { + type Mtbl = AtomicObject; + + type ParseError = A::ParseError; + + fn deserialize( + &self, + deserializer: &mut dyn Deserializer, + _resolver: Rc>, + ) -> ParseResult<'a, Ctx, Self> { + Ok(A::deserialize(deserializer)?.into()) + } + + fn unexpected_tail(&self, tail: &[u8]) -> Self::ParseError { + A::unexpected_tail(tail) + } +} + +/// Extension trait to provide method-like utilities associated with [AtomicObject]s. +pub trait ExtAtomicObject: Atomic { + /// Short-hand for getting specific [`AtomicFactory`]. + fn f() -> AtomicFactory; + /// Short-hand for getting specific [`AtomicObject`]. + fn m(self) -> AtomicObject; +} + +impl ExtAtomicObject for A { + fn f() -> AtomicFactory { + AtomicFactory::new() + } + fn m(self) -> AtomicObject { + self.into() + } +} + diff --git a/src/std/collections.rs b/src/std/collections.rs index 3061a44..edfa86f 100644 --- a/src/std/collections.rs +++ b/src/std/collections.rs @@ -1,3 +1,4 @@ //! Standard generic collections. +pub mod pair; pub mod stack; diff --git a/src/std/collections/pair.rs b/src/std/collections/pair.rs new file mode 100644 index 0000000..64319a0 --- /dev/null +++ b/src/std/collections/pair.rs @@ -0,0 +1,93 @@ +use std::error::Error; +use std::fmt::Display; + +use crate::core::*; +use crate::std::inlining::static_pair::*; +use crate::std::inlining::*; + +#[derive(Clone)] +pub struct Pair { + pub a: A, + pub b: B, +} + +impl StaticPairSerializable for Pair { + type SA = A; + type SB = B; + + fn s_elements(&self) -> (&Self::SA, &Self::SB) { + (&self.a, &self.b) + } +} + +#[derive(Debug)] +pub enum PairParseError { + A(ErrorA), + B(ErrorB), +} + +impl Display for PairParseError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + PairParseError::A(error) => f.write_fmt(format_args!( + "error while parsing first element of a pair: {}", + error + )), + PairParseError::B(error) => f.write_fmt(format_args!( + "error while parsing first element of a pair: {}", + error + )), + } + } +} + +impl Error for PairParseError {} + +impl<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>, B: Mentionable<'a, Ctx>> StaticPair<'a, Ctx> + for Pair +where + A::Fctr: InlineableFactory, +{ + type FactoryData = Pair; + type A = A; + type B = B; + type FA = A::Fctr; + type FB = B::Fctr; + type ParseError = PairParseError< + >::ParseError, + >::ParseError, + >; + + fn factories(factory_data: &Self::FactoryData) -> (&Self::FA, &Self::FB) { + (&factory_data.a, &factory_data.b) + } + + fn from_parsed(_factory_data: &Self::FactoryData, a: Self::A, b: Self::B) -> Self { + Pair { a, b } + } + + fn from_error_a( + _factory_data: &Self::FactoryData, + error: >::ParseError, + ) -> Self::ParseError { + PairParseError::A(error) + } + + fn from_error_b( + _factory_data: &Self::FactoryData, + error: >::ParseError, + ) -> Self::ParseError { + PairParseError::B(error) + } + + fn factory_data(&self) -> Self::FactoryData { + Pair { + a: self.a.factory(), + b: self.b.factory(), + } + } + + fn elements(&self) -> (&Self::A, &Self::B) { + (&self.a, &self.b) + } +} diff --git a/src/std/collections/stack.rs b/src/std/collections/stack.rs index 82bdd53..979f031 100644 --- a/src/std/collections/stack.rs +++ b/src/std/collections/stack.rs @@ -175,27 +175,29 @@ impl<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> ExtStack<'a, Ctx, A> for St #[cfg(test)] mod tests { use super::*; + use crate::std::atomic::atomic_object::*; use crate::std::atomic::plain::*; - use crate::std::atomic::*; use crate::testing::*; - type T = Stack<'static, TestContext, Plain>; + type T = Stack<'static, TestContext, AtomicObject>; - fn unstack(stack: &T) -> Result>, StackFaiure<'static, TestContext, Plain>> { + fn unstack( + stack: &T, + ) -> Result>, StackFaiure<'static, TestContext, AtomicObject>> { Ok(stack .clone() .vec()? .iter() - .map(|plain| plain.bytes()) + .map(|plain| plain.raw()) .collect()) } fn make_stack() -> T { let stack: T = Stack::empty(Plain::f()); - let stack: T = stack.add(Plain::from_slice(b"A0")); - let stack: T = stack.add(Plain::from_slice(b"B1")); - let stack: T = stack.add(Plain::from_slice(b"C2")); + let stack: T = stack.add(Plain::from_slice(b"A0").into()); + let stack: T = stack.add(Plain::from_slice(b"B1").into()); + let stack: T = stack.add(Plain::from_slice(b"C2").into()); stack } @@ -207,7 +209,7 @@ mod tests { } #[test] - fn test_stack() -> Result<(), StackFaiure<'static, TestContext, Plain>> { + fn test_stack() -> Result<(), StackFaiure<'static, TestContext, AtomicObject>> { let stack: T = make_stack(); validate_stack(&stack); @@ -244,5 +246,5 @@ impl<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> ConstSizeFactory where A::Fctr: ConstSizeFactory, { - const SIZE: usize = { Stack::<'a, Ctx, A>::SIZE + A::Fctr::SIZE }; + const SIZE: usize = Stack::<'a, Ctx, A>::SIZE + A::Fctr::SIZE; } diff --git a/src/std/inlining.rs b/src/std/inlining.rs index 478d7b2..7d4e0a3 100644 --- a/src/std/inlining.rs +++ b/src/std/inlining.rs @@ -1,6 +1,7 @@ -pub mod staticpair; +pub mod static_pair; use super::atomic::*; +use super::atomic::atomic_object::*; use crate::core::*; use crate::std::*; diff --git a/src/std/inlining/static_pair.rs b/src/std/inlining/static_pair.rs new file mode 100644 index 0000000..6214147 --- /dev/null +++ b/src/std/inlining/static_pair.rs @@ -0,0 +1,134 @@ +use super::*; +use crate::core::*; + +pub trait StaticPairSerializable { + type SA: Serializable; + type SB: Serializable; + + fn s_elements(&self) -> (&Self::SA, &Self::SB); +} + +pub trait StaticPair<'a, Ctx: 'a + Context>: + 'a + StaticPairSerializable +{ + type FactoryData: 'a + Clone; + type A: Mentionable<'a, Ctx, Fctr = Self::FA>; + type B: Mentionable<'a, Ctx, Fctr = Self::FB>; + type FA: Factory<'a, Ctx, Mtbl = Self::A> + InlineableFactory; + type FB: Factory<'a, Ctx, Mtbl = Self::B>; + type ParseError: 'a + Error; + + fn factories(factory_data: &Self::FactoryData) -> (&Self::FA, &Self::FB); + fn from_parsed(factory_data: &Self::FactoryData, a: Self::A, b: Self::B) -> Self; + fn from_error_a( + factory_data: &Self::FactoryData, + error: >::ParseError, + ) -> Self::ParseError; + fn from_error_b( + factory_data: &Self::FactoryData, + error: >::ParseError, + ) -> Self::ParseError; + fn factory_data(&self) -> Self::FactoryData; + fn elements(&self) -> (&Self::A, &Self::B); +} + +pub struct StaticPairObject { + pair: SP, +} + +pub struct StaticPairFactory<'a, Ctx: 'a + Context, SP: StaticPair<'a, Ctx>> { + factory_data: SP::FactoryData, +} + +impl Serializable for StaticPairObject { + fn serialize(&self, serializer: &mut dyn Serializer) { + let (a, b) = self.pair.s_elements(); + a.serialize(serializer); + b.serialize(serializer); + } +} + +impl<'a, Ctx: 'a + Context, SP: StaticPair<'a, Ctx>> Mentionable<'a, Ctx> for StaticPairObject { + type Fctr = StaticPairFactory<'a, Ctx, SP>; + + fn factory(&self) -> Self::Fctr { + StaticPairFactory { + factory_data: self.pair.factory_data(), + } + } + + fn points(&self) -> Vec>> { + let (a, b) = self.pair.elements(); + let mut vec = a.points(); + vec.extend(b.points()); + vec + } +} + +impl<'a, Ctx: 'a + Context, SP: StaticPair<'a, Ctx>> Clone for StaticPairFactory<'a, Ctx, SP> { + fn clone(&self) -> Self { + Self { + factory_data: self.factory_data.clone(), + } + } +} + +impl<'a, Ctx: 'a + Context, SP: StaticPair<'a, Ctx>> Factory<'a, Ctx> + for StaticPairFactory<'a, Ctx, SP> +{ + type Mtbl = StaticPairObject; + + type ParseError = SP::ParseError; + + fn deserialize( + &self, + deserializer: &mut dyn Deserializer, + resolver: Rc>, + ) -> ParseResult<'a, Ctx, Self> { + let (fa, fb) = SP::factories(&self.factory_data); + let a: SP::A = match fa.deserialize(deserializer, resolver.clone()) { + Ok(a) => a, + Err(error) => return Err(SP::from_error_a(&self.factory_data, error)), + }; + let b: SP::B = match fb.deserialize(deserializer, resolver) { + Ok(b) => b, + Err(error) => return Err(SP::from_error_b(&self.factory_data, error)), + }; + Ok(StaticPairObject { + pair: SP::from_parsed(&self.factory_data, a, b), + }) + } + + fn unexpected_tail(&self, tail: &[u8]) -> Self::ParseError { + let (_, fb) = SP::factories(&self.factory_data); + SP::from_error_b(&self.factory_data, fb.unexpected_tail(tail)) + } +} + +impl<'a, Ctx: 'a + Context, SP: StaticPair<'a, Ctx>> InlineableFactory + for StaticPairFactory<'a, Ctx, SP> +where + SP::FB: InlineableFactory, +{ +} + +impl<'a, Ctx: 'a + Context, SP: StaticPair<'a, Ctx>> FixedSizeFactory + for StaticPairFactory<'a, Ctx, SP> +where + SP::FA: FixedSizeFactory, + SP::FB: FixedSizeFactory, +{ + fn size(&self) -> usize { + let (fa, fb) = SP::factories(&self.factory_data); + fa.size() + fb.size() + } +} + +impl<'a, Ctx: 'a + Context, SP: StaticPair<'a, Ctx>> ConstSizeFactory + for StaticPairFactory<'a, Ctx, SP> +where + SP::FA: ConstSizeFactory, + SP::FB: ConstSizeFactory, +{ + const SIZE: usize = SP::FA::SIZE + SP::FB::SIZE; +} diff --git a/src/std/inlining/staticpair.rs b/src/std/inlining/staticpair.rs deleted file mode 100644 index 8b13789..0000000 --- a/src/std/inlining/staticpair.rs +++ /dev/null @@ -1 +0,0 @@ -