AtomicObject + StaticPair

This commit is contained in:
AF 2023-04-22 20:54:30 +00:00
parent 4f7df3ddb5
commit c08e769b82
8 changed files with 342 additions and 66 deletions

View File

@ -1,6 +1,7 @@
//! This module allows to describe a primitive subset of [Mentionable] types, [Atomic]s, //! This module allows to describe a primitive subset of [Mentionable] types, [Atomic]s,
//! simple static types, which are completely [Context]-independent. //! simple static types, which are completely [Context]-independent.
pub mod atomic_object;
pub mod plain; pub mod plain;
use std::marker::PhantomData; use std::marker::PhantomData;
@ -19,55 +20,6 @@ pub trait Atomic: 'static + Sized + Clone + Serializable {
fn unexpected_tail(tail: &[u8]) -> Self::ParseError; fn unexpected_tail(tail: &[u8]) -> Self::ParseError;
} }
/// Generic implementation of a factory for [Atomic]s.
pub struct AtomicFactory<A: Atomic>(PhantomData<A>);
impl<A: Atomic> AtomicFactory<A> {
fn new() -> Self {
AtomicFactory(PhantomData)
}
}
impl<A: Atomic> Clone for AtomicFactory<A> {
fn clone(&self) -> Self {
Self::new()
}
}
impl<'a, Ctx: 'a + Context, A: Atomic> Mentionable<'a, Ctx> for A {
type Fctr = AtomicFactory<A>;
fn factory(&self) -> Self::Fctr {
AtomicFactory::new()
}
fn topology(&self) -> Hash {
Ctx::hash(b"")
}
fn points(&self) -> Vec<Point<'a, Ctx, TypelessMentionable<'a, Ctx>>> {
vec![]
}
}
impl<'a, Ctx: 'a + Context, A: Atomic> Factory<'a, Ctx> for AtomicFactory<A> {
type Mtbl = A;
type ParseError = A::ParseError;
fn deserialize(
&self,
deserializer: &mut dyn Deserializer,
_resolver: Rc<dyn Resolver<'a, Ctx>>,
) -> ParseResult<'a, Ctx, Self> {
A::deserialize(deserializer)
}
fn unexpected_tail(&self, tail: &[u8]) -> Self::ParseError {
A::unexpected_tail(tail)
}
}
fn _parse_slice<A: Atomic>(slice: &[u8]) -> Result<A, A::ParseError> { fn _parse_slice<A: Atomic>(slice: &[u8]) -> Result<A, A::ParseError> {
let mut deserializer = SliceDeserializer::from(slice); let mut deserializer = SliceDeserializer::from(slice);
let mentionable = A::deserialize(&mut deserializer)?; let mentionable = A::deserialize(&mut deserializer)?;
@ -81,17 +33,11 @@ fn _parse_slice<A: Atomic>(slice: &[u8]) -> Result<A, A::ParseError> {
/// Extension trait to provide method-like utilities associated with [Atomic]s. /// Extension trait to provide method-like utilities associated with [Atomic]s.
pub trait ExtAtomic: Atomic { pub trait ExtAtomic: Atomic {
/// Short-hand for getting specific [`AtomicFactory`].
fn f() -> AtomicFactory<Self>;
/// Static equivalent of [`ExtFactory::parse_slice`]. /// Static equivalent of [`ExtFactory::parse_slice`].
fn parse_slice(slice: &[u8]) -> Result<Self, Self::ParseError>; fn parse_slice(slice: &[u8]) -> Result<Self, Self::ParseError>;
} }
impl<A: Atomic> ExtAtomic for A { impl<A: Atomic> ExtAtomic for A {
fn f() -> AtomicFactory<Self> {
AtomicFactory::new()
}
fn parse_slice(slice: &[u8]) -> Result<Self, Self::ParseError> { fn parse_slice(slice: &[u8]) -> Result<Self, Self::ParseError> {
_parse_slice(slice) _parse_slice(slice)
} }

View File

@ -0,0 +1,100 @@
use std::ops::Deref;
use super::*;
pub struct AtomicObject<A: Atomic> {
atomic: A,
}
impl<A: Atomic> From<A> for AtomicObject<A> {
fn from(value: A) -> Self {
Self { atomic: value }
}
}
impl<A: Atomic> AsRef<A> for AtomicObject<A> {
fn as_ref(&self) -> &A {
&self.atomic
}
}
impl<A: Atomic> Deref for AtomicObject<A> {
type Target = A;
fn deref(&self) -> &Self::Target {
&self.atomic
}
}
impl<A: Atomic> Serializable for AtomicObject<A> {
fn serialize(&self, serializer: &mut dyn Serializer) {
self.atomic.serialize(serializer)
}
}
impl<'a, Ctx: 'a + Context, A: Atomic> Mentionable<'a, Ctx> for AtomicObject<A> {
type Fctr = AtomicFactory<A>;
fn factory(&self) -> Self::Fctr {
AtomicFactory::new()
}
fn topology(&self) -> Hash {
Ctx::hash(b"")
}
fn points(&self) -> Vec<Point<'a, Ctx, TypelessMentionable<'a, Ctx>>> {
vec![]
}
}
/// Generic implementation of a factory for [Atomic]s.
pub struct AtomicFactory<A: Atomic>(PhantomData<A>);
impl<A: Atomic> AtomicFactory<A> {
fn new() -> Self {
AtomicFactory(PhantomData)
}
}
impl<A: Atomic> Clone for AtomicFactory<A> {
fn clone(&self) -> Self {
Self::new()
}
}
impl<'a, Ctx: 'a + Context, A: Atomic> Factory<'a, Ctx> for AtomicFactory<A> {
type Mtbl = AtomicObject<A>;
type ParseError = A::ParseError;
fn deserialize(
&self,
deserializer: &mut dyn Deserializer,
_resolver: Rc<dyn Resolver<'a, Ctx>>,
) -> 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<Self>;
/// Short-hand for getting specific [`AtomicObject`].
fn m(self) -> AtomicObject<Self>;
}
impl<A: Atomic> ExtAtomicObject for A {
fn f() -> AtomicFactory<Self> {
AtomicFactory::new()
}
fn m(self) -> AtomicObject<Self> {
self.into()
}
}

View File

@ -1,3 +1,4 @@
//! Standard generic collections. //! Standard generic collections.
pub mod pair;
pub mod stack; pub mod stack;

View File

@ -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<A, B> {
pub a: A,
pub b: B,
}
impl<A: Serializable, B: Serializable> StaticPairSerializable for Pair<A, B> {
type SA = A;
type SB = B;
fn s_elements(&self) -> (&Self::SA, &Self::SB) {
(&self.a, &self.b)
}
}
#[derive(Debug)]
pub enum PairParseError<ErrorA: Error, ErrorB: Error> {
A(ErrorA),
B(ErrorB),
}
impl<ErrorA: Error, ErrorB: Error> Display for PairParseError<ErrorA, ErrorB> {
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<ErrorA: Error, ErrorB: Error> Error for PairParseError<ErrorA, ErrorB> {}
impl<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>, B: Mentionable<'a, Ctx>> StaticPair<'a, Ctx>
for Pair<A, B>
where
A::Fctr: InlineableFactory,
{
type FactoryData = Pair<Self::FA, Self::FB>;
type A = A;
type B = B;
type FA = A::Fctr;
type FB = B::Fctr;
type ParseError = PairParseError<
<A::Fctr as Factory<'a, Ctx>>::ParseError,
<B::Fctr as Factory<'a, Ctx>>::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: <Self::FA as Factory<'a, Ctx>>::ParseError,
) -> Self::ParseError {
PairParseError::A(error)
}
fn from_error_b(
_factory_data: &Self::FactoryData,
error: <Self::FB as Factory<'a, Ctx>>::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)
}
}

View File

@ -175,27 +175,29 @@ impl<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> ExtStack<'a, Ctx, A> for St
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use crate::std::atomic::atomic_object::*;
use crate::std::atomic::plain::*; use crate::std::atomic::plain::*;
use crate::std::atomic::*;
use crate::testing::*; use crate::testing::*;
type T = Stack<'static, TestContext, Plain>; type T = Stack<'static, TestContext, AtomicObject<Plain>>;
fn unstack(stack: &T) -> Result<Vec<Vec<u8>>, StackFaiure<'static, TestContext, Plain>> { fn unstack(
stack: &T,
) -> Result<Vec<Vec<u8>>, StackFaiure<'static, TestContext, AtomicObject<Plain>>> {
Ok(stack Ok(stack
.clone() .clone()
.vec()? .vec()?
.iter() .iter()
.map(|plain| plain.bytes()) .map(|plain| plain.raw())
.collect()) .collect())
} }
fn make_stack() -> T { fn make_stack() -> T {
let stack: T = Stack::empty(Plain::f()); 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"A0").into());
let stack: T = stack.add(Plain::from_slice(b"B1")); let stack: T = stack.add(Plain::from_slice(b"B1").into());
let stack: T = stack.add(Plain::from_slice(b"C2")); let stack: T = stack.add(Plain::from_slice(b"C2").into());
stack stack
} }
@ -207,7 +209,7 @@ mod tests {
} }
#[test] #[test]
fn test_stack() -> Result<(), StackFaiure<'static, TestContext, Plain>> { fn test_stack() -> Result<(), StackFaiure<'static, TestContext, AtomicObject<Plain>>> {
let stack: T = make_stack(); let stack: T = make_stack();
validate_stack(&stack); validate_stack(&stack);
@ -244,5 +246,5 @@ impl<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> ConstSizeFactory
where where
A::Fctr: ConstSizeFactory, 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;
} }

View File

@ -1,6 +1,7 @@
pub mod staticpair; pub mod static_pair;
use super::atomic::*; use super::atomic::*;
use super::atomic::atomic_object::*;
use crate::core::*; use crate::core::*;
use crate::std::*; use crate::std::*;

View File

@ -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<SA = Self::A, SB = Self::B>
{
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: <Self::FA as Factory<'a, Ctx>>::ParseError,
) -> Self::ParseError;
fn from_error_b(
factory_data: &Self::FactoryData,
error: <Self::FB as Factory<'a, Ctx>>::ParseError,
) -> Self::ParseError;
fn factory_data(&self) -> Self::FactoryData;
fn elements(&self) -> (&Self::A, &Self::B);
}
pub struct StaticPairObject<SP> {
pair: SP,
}
pub struct StaticPairFactory<'a, Ctx: 'a + Context, SP: StaticPair<'a, Ctx>> {
factory_data: SP::FactoryData,
}
impl<SP: StaticPairSerializable> Serializable for StaticPairObject<SP> {
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<SP> {
type Fctr = StaticPairFactory<'a, Ctx, SP>;
fn factory(&self) -> Self::Fctr {
StaticPairFactory {
factory_data: self.pair.factory_data(),
}
}
fn points(&self) -> Vec<Point<'a, Ctx, TypelessMentionable<'a, Ctx>>> {
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<SP>;
type ParseError = SP::ParseError;
fn deserialize(
&self,
deserializer: &mut dyn Deserializer,
resolver: Rc<dyn Resolver<'a, Ctx>>,
) -> 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;
}

View File

@ -1 +0,0 @@