From 54a6912baf715816e3dcbfd074c0e2d7b8c74fe3 Mon Sep 17 00:00:00 2001 From: timofey Date: Sat, 29 Jul 2023 00:17:27 +0000 Subject: [PATCH] `InliningMode` --- src/rcore.rs | 19 +++++-- src/rcore/modes.rs | 48 +++++++++--------- src/rcore/origin.rs | 4 +- src/rcore/point.rs | 8 +-- src/rcore/points.rs | 4 +- src/rcore/resolution.rs | 4 +- src/rcore/resolver_origin.rs | 7 ++- src/rstd/atomic.rs | 6 +-- src/rstd/atomic/array.rs | 12 +---- src/rstd/atomic/atomic_object.rs | 9 ++-- src/rstd/atomic/au64.rs | 12 +---- src/rstd/atomic/boolean.rs | 12 +---- src/rstd/atomic/modes.rs | 34 ++++++------- src/rstd/cast.rs | 2 +- src/rstd/collections/stack.rs | 85 ++++++++++++++++++++++++++------ src/rstd/collections/tree.rs | 31 +++--------- src/rstd/inlining.rs | 9 +++- src/rstd/inlining/modes.rs | 33 +++++++++++++ src/rstd/inlining/static_pair.rs | 12 +++-- src/rstd/nullable.rs | 28 ++++------- src/rstd/point.rs | 18 ++----- src/rstd/typeless.rs | 4 +- 22 files changed, 225 insertions(+), 176 deletions(-) create mode 100644 src/rstd/inlining/modes.rs diff --git a/src/rcore.rs b/src/rcore.rs index bb43b31..0ce8b6b 100644 --- a/src/rcore.rs +++ b/src/rcore.rs @@ -49,9 +49,9 @@ pub use self::slice_deserializer::SliceDeserializer; pub type Wrapped<'a, Ctx, A> = WrapC<'a, A, Ctx>; /// Fundamental trait for ADN objects. -pub trait Mentionable<'a, Ctx: Context<'a>>: 'a + Serializable { +pub trait MentionableBase<'a, Ctx: Context<'a>>: 'a + Serializable + Sized { /// Type of the associated factory. - type Fctr: Factory<'a, Ctx, Mtbl = Self>; + type Fctr: FactoryBase<'a, Ctx, Mtbl = Self>; /// Value of the associated factory. fn factory(&self) -> Self::Fctr; @@ -67,8 +67,19 @@ pub trait Mentionable<'a, Ctx: Context<'a>>: 'a + Serializable { fn points_typed(&self, points: &mut impl PointsVisitor<'a, Ctx>); } +pub trait Mentionable<'a, Ctx: Context<'a>>: MentionableBase<'a, Ctx, Fctr = Self::_Fctr> { + type _Fctr: Factory<'a, Ctx, Mtbl = Self>; +} + +impl<'a, Ctx: Context<'a>, A: MentionableBase<'a, Ctx>> Mentionable<'a, Ctx> for A +where + Self::Fctr: Factory<'a, Ctx>, +{ + type _Fctr = Self::Fctr; +} + /// [`Factory`] associated with the [`Mentionable`]. Mostly useful for `type` definitions. -pub type Fctr<'a, Ctx, A> = >::Fctr; +pub type Fctr<'a, Ctx, A> = >::Fctr; /// Shorthand for the type of vaalues returned by [`Factory::deserialize`]. pub type ParseResult<'a, Ctx, F> = Result, ParseError<'a, Ctx, F>>; @@ -79,7 +90,7 @@ pub type ParseResultA<'a, Ctx, A> = Result>; /// [Factory] base. pub trait FactoryBase<'a, Ctx: Context<'a>>: 'a + Send + Sync + Clone { /// Type of the associated objects. - type Mtbl: Mentionable<'a, Ctx, Fctr = Self>; + type Mtbl: MentionableBase<'a, Ctx, Fctr = Self>; /// Type of an error that [`Factory::deserialize`] can fail with. type ParseError: 'a + Error; } diff --git a/src/rcore/modes.rs b/src/rcore/modes.rs index f3a97e7..2a3eaad 100644 --- a/src/rcore/modes.rs +++ b/src/rcore/modes.rs @@ -6,25 +6,16 @@ pub trait ParseMode { type Mode: ?Sized; } -pub struct RegularMode; - -pub trait RegularFactory<'a, Ctx: Context<'a>>: - FactoryBase<'a, Ctx> + ParseMode -{ - fn rdeserialize(&self, inctx: impl InCtx<'a, Ctx>) -> ParseResult<'a, Ctx, Self>; - fn rextend(&self, mentionable: Self::Mtbl, tail: &[u8]) -> ParseResult<'a, Ctx, Self>; -} - pub trait WithParseMode: ParseMode { type WithMode: ?Sized; } -pub struct WithMode(PhantomData, T); - impl WithParseMode for T { type WithMode = WithMode::Mode>; } +pub struct WithMode(PhantomData, T); + pub trait FactoryProxy<'a, Ctx: Context<'a>> { type F: FactoryBase<'a, Ctx> + ParseMode; @@ -36,6 +27,28 @@ pub trait FactoryProxy<'a, Ctx: Context<'a>> { ) -> ParseResult<'a, Ctx, Self::F>; } +impl<'a, Ctx: Context<'a>, F: FactoryBase<'a, Ctx> + WithParseMode> Factory<'a, Ctx> for F +where + F::WithMode: FactoryProxy<'a, Ctx, F = Self>, +{ + fn deserialize(&self, inctx: impl InCtx<'a, Ctx>) -> ParseResult<'a, Ctx, Self> { + >::pdeserialize(self, inctx) + } + + fn extend(&self, mentionable: Self::Mtbl, tail: &[u8]) -> ParseResult<'a, Ctx, Self> { + >::pextend(self, mentionable, tail) + } +} + +pub struct RegularMode; + +pub trait RegularFactory<'a, Ctx: Context<'a>>: + FactoryBase<'a, Ctx> + ParseMode +{ + fn rdeserialize(&self, inctx: impl InCtx<'a, Ctx>) -> ParseResult<'a, Ctx, Self>; + fn rextend(&self, mentionable: Self::Mtbl, tail: &[u8]) -> ParseResult<'a, Ctx, Self>; +} + impl<'a, Ctx: Context<'a>, F: RegularFactory<'a, Ctx>> FactoryProxy<'a, Ctx> for WithMode { @@ -53,16 +66,3 @@ impl<'a, Ctx: Context<'a>, F: RegularFactory<'a, Ctx>> FactoryProxy<'a, Ctx> f.rextend(mentionable, tail) } } - -impl<'a, Ctx: Context<'a>, F: FactoryBase<'a, Ctx> + WithParseMode> Factory<'a, Ctx> for F -where - F::WithMode: FactoryProxy<'a, Ctx, F = Self>, -{ - fn deserialize(&self, inctx: impl InCtx<'a, Ctx>) -> ParseResult<'a, Ctx, Self> { - >::pdeserialize(self, inctx) - } - - fn extend(&self, mentionable: Self::Mtbl, tail: &[u8]) -> ParseResult<'a, Ctx, Self> { - >::pextend(self, mentionable, tail) - } -} diff --git a/src/rcore/origin.rs b/src/rcore/origin.rs index 2817ee3..4dd8a1f 100644 --- a/src/rcore/origin.rs +++ b/src/rcore/origin.rs @@ -7,7 +7,9 @@ pub trait Origin<'a, Ctx: Context<'a>>: 'a { /// Clone the associated factory. fn factory(&self) -> OFctr<'a, Ctx, Self>; /// Try resolving the value. - fn resolve(self: Rc) -> Resolution<'a, Ctx, Self::Mtbl>; + fn resolve(self: Rc) -> Resolution<'a, Ctx, Self::Mtbl> + where + OFctr<'a, Ctx, Self>: Factory<'a, Ctx>; /// Try resolving the bytes. Should avoid parsing the value. fn resolve_bytes(self: Rc) -> HashResolution<'a, Ctx>; } diff --git a/src/rcore/point.rs b/src/rcore/point.rs index f0bad20..648e94f 100644 --- a/src/rcore/point.rs +++ b/src/rcore/point.rs @@ -1,23 +1,23 @@ use super::*; /// The main way to represent a reference in ADN. -pub struct Point<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx>> { +pub struct Point<'a, Ctx: Context<'a>, A: MentionableBase<'a, Ctx>> { /// Hash of the referred content. /// Derived both from the serialised value ([`Serializable::serialize`]) - /// and its topology ([`Mentionable::topology`]). + /// and its topology ([`MentionableBase::topology`]). pub point: Hash, /// [Origin] used in [`Point::resolve`]. pub origin: Rc>, } -impl<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx>> PartialEq for Point<'a, Ctx, A> { +impl<'a, Ctx: Context<'a>, A: MentionableBase<'a, Ctx>> PartialEq for Point<'a, Ctx, A> { /// Note: this doesn't check for [Factory] equality. fn eq(&self, other: &Self) -> bool { self.point == other.point } } -impl<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx>> Clone for Point<'a, Ctx, A> { +impl<'a, Ctx: Context<'a>, A: MentionableBase<'a, Ctx>> Clone for Point<'a, Ctx, A> { fn clone(&self) -> Self { Self { point: self.point, diff --git a/src/rcore/points.rs b/src/rcore/points.rs index cc5108b..30b596d 100644 --- a/src/rcore/points.rs +++ b/src/rcore/points.rs @@ -1,13 +1,13 @@ use super::*; -/// Visitor used in [`Mentionable::points_typed`]. +/// Visitor used in [`MentionableBase::points_typed`]. pub trait PointsVisitor<'a, Ctx: Context<'a>> { /// Visit a [Point]. fn visit>(&mut self, point: &Point<'a, Ctx, A>); } impl<'a, Ctx: Context<'a>> PointsVisitor<'a, Ctx> for Vec { - /// The only natural implementation, as used in [`Mentionable::topology`]. + /// The only natural implementation, as used in [`MentionableBase::topology`]. fn visit>(&mut self, point: &Point<'a, Ctx, A>) { self.extend(point.point) } diff --git a/src/rcore/resolution.rs b/src/rcore/resolution.rs index a10d5e0..0fd0a15 100644 --- a/src/rcore/resolution.rs +++ b/src/rcore/resolution.rs @@ -44,14 +44,14 @@ pub type HashResolution<'a, Ctx> = Wrapped<'a, Ctx, HashResolutionResult<'a, Ctx #[derive(Clone, Copy, Debug)] pub struct Address { pub point: Hash, - /// Index of the point in the [`Mentionable::points_typed()`]. + /// Index of the point in the [`MentionableBase::points_typed()`]. pub index: usize, } /// Trait representing the "rainbow table" behaviour. pub trait Resolver<'a, Ctx: Context<'a>>: 'a { /// Successfully returned value should be the inverse of the point passed - /// with topology header ([`Mentionable::topology()`]) omitted. + /// with topology header ([`MentionableBase::topology()`]) omitted. fn resolve(self: Rc, address: Address) -> HashResolution<'a, Ctx>; } diff --git a/src/rcore/resolver_origin.rs b/src/rcore/resolver_origin.rs index 01460c6..4a88585 100644 --- a/src/rcore/resolver_origin.rs +++ b/src/rcore/resolver_origin.rs @@ -18,7 +18,7 @@ impl<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx>> Point<'a, Ctx, A> { } } -struct ResolverOrigin<'a, Ctx: Context<'a>, F: Factory<'a, Ctx>> { +struct ResolverOrigin<'a, Ctx: Context<'a>, F: FactoryBase<'a, Ctx>> { r_factory: F, r_address: Address, r_resolver: Rc>, @@ -47,7 +47,10 @@ impl<'a, Ctx: Context<'a>, F: Factory<'a, Ctx>> Origin<'a, Ctx> for ResolverOrig self.r_factory.clone() } - fn resolve(self: Rc) -> Resolution<'a, Ctx, Self::Mtbl> { + fn resolve(self: Rc) -> Resolution<'a, Ctx, Self::Mtbl> + where + OFctr<'a, Ctx, Self>: Factory<'a, Ctx>, + { _resolve_origin(self) } diff --git a/src/rstd/atomic.rs b/src/rstd/atomic.rs index 1d0555e..c6ad432 100644 --- a/src/rstd/atomic.rs +++ b/src/rstd/atomic.rs @@ -12,16 +12,16 @@ use std::marker::PhantomData; use crate::rcore::*; -pub use self::modes::{AtomicProxy, RegularAtomic}; - use super::*; +pub use self::modes::{AtomicProxy, RegularAtomic}; + pub type AParseError = ::AParseError; pub type AParseResult = Result>; /// This trait combines functionality of [`Mentionable`] and [`Factory`], -/// while limiting [`Mentionable::points_typed`] (and corresponding [`Mentionable::topology`]) +/// while limiting [`MentionableBase::points_typed`] (and corresponding [`MentionableBase::topology`]) /// to an empty sequence. pub trait AtomicBase: 'static + Send + Sync + Send + Clone + Serializable { /// Equivalent of [`FactoryBase::ParseError`]. diff --git a/src/rstd/atomic/array.rs b/src/rstd/atomic/array.rs index 5046aca..3e68ce2 100644 --- a/src/rstd/atomic/array.rs +++ b/src/rstd/atomic/array.rs @@ -39,17 +39,7 @@ impl AtomicBase for [u8; N] { } impl ParseMode for [u8; N] { - type Mode = RegularMode; -} - -impl RegularAtomic for [u8; N] { - fn ra_deserialize(inlining: impl Inlining) -> AParseResult { - Self::a_ideserialize(inlining).seal() - } - - fn ra_extend(self, tail: &[u8]) -> AParseResult { - Err(Self::a_extension_error(tail)) - } + type Mode = InliningMode; } impl InlineableAtomic for [u8; N] { diff --git a/src/rstd/atomic/atomic_object.rs b/src/rstd/atomic/atomic_object.rs index 3f9b3ed..12c6b06 100644 --- a/src/rstd/atomic/atomic_object.rs +++ b/src/rstd/atomic/atomic_object.rs @@ -37,14 +37,15 @@ impl Serializable for AtomicObject { } pub trait AoProxy<'a, Ctx: Context<'a>>: AtomicProxy { - type Mtbl: Mentionable<'a, Ctx, Fctr = Self::Fctr>; + type Mtbl: MentionableBase<'a, Ctx, Fctr = Self::Fctr>; type Fctr: Factory<'a, Ctx, Mtbl = Self::Mtbl>; fn factory() -> Self::Fctr; fn wrap(a: Self::A) -> Self::Mtbl; } -impl<'a, Ctx: Context<'a>, A: AtomicBase + WithParseMode> Mentionable<'a, Ctx> for AtomicObject +impl<'a, Ctx: Context<'a>, A: AtomicBase + WithParseMode> MentionableBase<'a, Ctx> + for AtomicObject where A::WithMode: AoProxy<'a, Ctx, Mtbl = Self, A = A>, { @@ -87,8 +88,8 @@ where type ParseError = A::AParseError; } -impl ParseMode for AtomicFactory { - type Mode = RegularMode; +impl ParseMode for AtomicFactory { + type Mode = A::Mode; } impl<'a, Ctx: Context<'a>, A: RegularAtomic> AoProxy<'a, Ctx> for WithMode { diff --git a/src/rstd/atomic/au64.rs b/src/rstd/atomic/au64.rs index b4917d4..309fc2d 100644 --- a/src/rstd/atomic/au64.rs +++ b/src/rstd/atomic/au64.rs @@ -39,17 +39,7 @@ impl AtomicBase for u64 { } impl ParseMode for u64 { - type Mode = RegularMode; -} - -impl RegularAtomic for u64 { - fn ra_deserialize(inlining: impl Inlining) -> AParseResult { - Self::a_ideserialize(inlining).seal() - } - - fn ra_extend(self, tail: &[u8]) -> AParseResult { - Err(Self::a_extension_error(tail)) - } + type Mode = InliningMode; } impl InlineableAtomic for u64 { diff --git a/src/rstd/atomic/boolean.rs b/src/rstd/atomic/boolean.rs index b873a08..7c30eb4 100644 --- a/src/rstd/atomic/boolean.rs +++ b/src/rstd/atomic/boolean.rs @@ -46,17 +46,7 @@ impl AtomicBase for bool { } impl ParseMode for bool { - type Mode = RegularMode; -} - -impl RegularAtomic for bool { - fn ra_deserialize(inlining: impl Inlining) -> AParseResult { - Self::a_ideserialize(inlining).seal() - } - - fn ra_extend(self, tail: &[u8]) -> AParseResult { - Err(Self::a_extension_error(tail)) - } + type Mode = InliningMode; } impl InlineableAtomic for bool { diff --git a/src/rstd/atomic/modes.rs b/src/rstd/atomic/modes.rs index f58d6ba..50f8b83 100644 --- a/src/rstd/atomic/modes.rs +++ b/src/rstd/atomic/modes.rs @@ -1,10 +1,5 @@ use super::*; -pub trait RegularAtomic: AtomicBase + ParseMode { - fn ra_deserialize(inlining: impl Inlining) -> AParseResult; - fn ra_extend(self, tail: &[u8]) -> AParseResult; -} - pub trait AtomicProxy { type A: AtomicBase + ParseMode; @@ -12,18 +7,6 @@ pub trait AtomicProxy { fn pa_extend(a: Self::A, tail: &[u8]) -> AParseResult; } -impl AtomicProxy for WithMode { - type A = A; - - fn pa_deserialize(inlining: impl Inlining) -> AParseResult { - A::ra_deserialize(inlining) - } - - fn pa_extend(a: Self::A, tail: &[u8]) -> AParseResult { - a.ra_extend(tail) - } -} - impl Atomic for A where A::WithMode: AtomicProxy, @@ -36,3 +19,20 @@ where ::pa_extend(self, tail) } } + +pub trait RegularAtomic: AtomicBase + ParseMode { + fn ra_deserialize(inlining: impl Inlining) -> AParseResult; + fn ra_extend(self, tail: &[u8]) -> AParseResult; +} + +impl AtomicProxy for WithMode { + type A = A; + + fn pa_deserialize(inlining: impl Inlining) -> AParseResult { + A::ra_deserialize(inlining) + } + + fn pa_extend(a: Self::A, tail: &[u8]) -> AParseResult { + a.ra_extend(tail) + } +} diff --git a/src/rstd/cast.rs b/src/rstd/cast.rs index 44d0107..26ac748 100644 --- a/src/rstd/cast.rs +++ b/src/rstd/cast.rs @@ -24,7 +24,7 @@ pub enum CastError<'a> { /// If you don't know what that means, it's a good idea to [`panic!`]. /// Happens due to internal resolver using indices rather than `point`s. /// This error usually indicates inconsistent behaviour - /// of [`Mentionable::points_typed`] and/or [`Mentionable::topology`]. + /// of [`MentionableBase::points_typed`] and/or [`MentionableBase::topology`]. AddressIndexOutOfBounds { index: usize, length: usize, diff --git a/src/rstd/collections/stack.rs b/src/rstd/collections/stack.rs index add0670..0284e37 100644 --- a/src/rstd/collections/stack.rs +++ b/src/rstd/collections/stack.rs @@ -5,7 +5,7 @@ use crate::rcore::*; use crate::rstd::{inlining::*, nullable::*, point::*, *}; /// Node containing a (nullable) reference to the next node and an element. -pub struct StackNode<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx>> { +pub struct StackNode<'a, Ctx: Context<'a>, A: StackCompatible<'a, Ctx>> { /// Reference comes first due to being inlineable. pub rest: Stack<'a, Ctx, A>, /// Unlike the original implementation in Python, doesn't default to using Point. @@ -28,14 +28,59 @@ impl StackNodeFactory { } } -impl<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx>> Serializable for StackNode<'a, Ctx, A> { +impl<'a, Ctx: Context<'a>, A: StackCompatible<'a, Ctx>> Serializable for StackNode<'a, Ctx, A> { fn serialize(&self, serializer: &mut dyn Serializer) { self.rest.serialize(serializer); self.element.serialize(serializer); } } -impl<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx>> Mentionable<'a, Ctx> for StackNode<'a, Ctx, A> { +pub trait StackCompatible<'a, Ctx: Context<'a>>: Mentionable<'a, Ctx> { + fn points_typed_rest(stack: &Stack<'a, Ctx, Self>, points: &mut impl PointsVisitor<'a, Ctx>); +} + +pub trait StackCompatibleProxy<'a, Ctx: Context<'a>, T>: FactoryProxy<'a, Ctx> +where + Self::F: Factory<'a, Ctx>, +{ + fn points_typed_rest(stack: &T, points: &mut impl PointsVisitor<'a, Ctx>); +} + +impl<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx>> StackCompatible<'a, Ctx> for A +where + as WithParseMode>::WithMode: + StackCompatibleProxy<'a, Ctx, Stack<'a, Ctx, A>, F = Fctr<'a, Ctx, A>>, +{ + fn points_typed_rest(stack: &Stack<'a, Ctx, Self>, points: &mut impl PointsVisitor<'a, Ctx>) { + < as WithParseMode>::WithMode as StackCompatibleProxy<'a, Ctx, _>>::points_typed_rest(stack, points) + } +} + +impl<'a, Ctx: Context<'a>, F: RegularFactory<'a, Ctx>> + StackCompatibleProxy<'a, Ctx, Stack<'a, Ctx, Mtbl<'a, Ctx, F>>> for WithMode +{ + fn points_typed_rest( + stack: &Stack<'a, Ctx, Mtbl<'a, Ctx, Self::F>>, + points: &mut impl PointsVisitor<'a, Ctx>, + ) { + stack.points_typed(points) + } +} + +impl<'a, Ctx: Context<'a>, F: InlineableFactory<'a, Ctx>> + StackCompatibleProxy<'a, Ctx, Stack<'a, Ctx, Mtbl<'a, Ctx, F>>> for WithMode +{ + fn points_typed_rest( + stack: &Stack<'a, Ctx, Mtbl<'a, Ctx, Self::F>>, + points: &mut impl PointsVisitor<'a, Ctx>, + ) { + stack.points_typed(points) + } +} + +impl<'a, Ctx: Context<'a>, A: StackCompatible<'a, Ctx>> MentionableBase<'a, Ctx> + for StackNode<'a, Ctx, A> +{ type Fctr = StackNodeFactory; fn factory(&self) -> Self::Fctr { @@ -43,7 +88,7 @@ impl<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx>> Mentionable<'a, Ctx> for Sta } fn points_typed(&self, points: &mut impl PointsVisitor<'a, Ctx>) { - self.rest.points_typed(points); + >::points_typed_rest(&self.rest, points); self.element.points_typed(points); } } @@ -81,23 +126,28 @@ impl StackNodeFactory { inctx: I, ) -> IParseResult<'a, Ctx, NullableFactory, I> where - F: FactoryBase<'a, Ctx>, + StackNodeFactory: Factory<'a, Ctx>, { NullableFactory::new(self.clone()).ideserialize(inctx) } } -impl<'a, Ctx: Context<'a>, F: FactoryBase<'a, Ctx>> FactoryBase<'a, Ctx> for StackNodeFactory { +impl<'a, Ctx: Context<'a>, F: Factory<'a, Ctx>> FactoryBase<'a, Ctx> for StackNodeFactory +where + F::Mtbl: StackCompatible<'a, Ctx, _Fctr = F>, +{ type Mtbl = StackNode<'a, Ctx, F::Mtbl>; type ParseError = StackParseError>; } -impl ParseMode for StackNodeFactory { - type Mode = RegularMode; +impl ParseMode for StackNodeFactory { + type Mode = F::Mode; } -impl<'a, Ctx: Context<'a>, F: Factory<'a, Ctx>> RegularFactory<'a, Ctx> for StackNodeFactory { +impl<'a, Ctx: Context<'a>, F: RegularFactory<'a, Ctx>> RegularFactory<'a, Ctx> + for StackNodeFactory +{ fn rdeserialize(&self, inctx: impl InCtx<'a, Ctx>) -> ParseResult<'a, Ctx, Self> { let (rest, inctx) = self.parse_point(inctx)?; let element = self @@ -126,7 +176,9 @@ pub type StackVecResult<'a, Ctx, A> = Result, StackFaiure<'a, Ctx, A>>; pub type StackVecWrapped<'a, Ctx, A> = Wrapped<'a, Ctx, StackVecResult<'a, Ctx, A>>; /// Extention trait with helper methods for [Stack]s. -pub trait ExtStack<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx>>: Mentionable<'a, Ctx> { +pub trait ExtStack<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx>>: + MentionableBase<'a, Ctx> +{ /// Get an empty stack ([`Nullable::Null`]). fn empty(factory: A::Fctr) -> Self; /// Get the corresponding factory. @@ -138,14 +190,17 @@ pub trait ExtStack<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx>>: Mentionable<' } /// Extention trait with helper methods for [Stack]s. -pub trait ExtStackClone<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx> + Clone>: - Mentionable<'a, Ctx> +pub trait ExtStackClone<'a, Ctx: Context<'a>, A: StackCompatible<'a, Ctx> + Clone>: + MentionableBase<'a, Ctx> { /// Collect all the elements into a [`Vec`]. fn vec(self) -> StackVecWrapped<'a, Ctx, A>; } -impl<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx>> ExtStack<'a, Ctx, A> for Stack<'a, Ctx, A> { +impl<'a, Ctx: Context<'a>, A: StackCompatible<'a, Ctx>> ExtStack<'a, Ctx, A> for Stack<'a, Ctx, A> +where + Fctr<'a, Ctx, StackNode<'a, Ctx, A>>: Factory<'a, Ctx>, +{ fn empty(factory: A::Fctr) -> Self { Nullable::Null(StackNodeFactory::new(factory.clone())) } @@ -163,8 +218,10 @@ impl<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx>> ExtStack<'a, Ctx, A> for Sta } } -impl<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx> + Clone> ExtStackClone<'a, Ctx, A> +impl<'a, Ctx: Context<'a>, A: StackCompatible<'a, Ctx> + Clone> ExtStackClone<'a, Ctx, A> for Stack<'a, Ctx, A> +where + Fctr<'a, Ctx, StackNode<'a, Ctx, A>>: Factory<'a, Ctx>, { fn vec(self) -> StackVecWrapped<'a, Ctx, A> { Ctx::T::iterate_mut((vec![], self), |(mut vec, stack)| match stack { diff --git a/src/rstd/collections/tree.rs b/src/rstd/collections/tree.rs index 618e50a..338372b 100644 --- a/src/rstd/collections/tree.rs +++ b/src/rstd/collections/tree.rs @@ -5,12 +5,7 @@ use std::{error::Error, fmt::Display}; use crate::{ flow::binary::*, rcore::*, - rstd::{ - atomic::{au64::*, *}, - inlining::*, - nullable::*, - point::*, - }, + rstd::{atomic::au64::*, inlining::*, nullable::*, point::*}, }; #[derive(Debug)] @@ -105,7 +100,7 @@ impl<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx>> Serializable for Tree<'a, Ct } } -impl<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx>> Mentionable<'a, Ctx> for Node<'a, Ctx, A> { +impl<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx>> MentionableBase<'a, Ctx> for Node<'a, Ctx, A> { type Fctr = NodeFactory; fn factory(&self) -> Self::Fctr { @@ -119,7 +114,7 @@ impl<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx>> Mentionable<'a, Ctx> for Nod } } -impl<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx>> Mentionable<'a, Ctx> for Tree<'a, Ctx, A> { +impl<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx>> MentionableBase<'a, Ctx> for Tree<'a, Ctx, A> { type Fctr = TreeFactory; fn factory(&self) -> Self::Fctr { @@ -131,7 +126,7 @@ impl<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx>> Mentionable<'a, Ctx> for Tre } } -impl<'a, Ctx: Context<'a>, F: FactoryBase<'a, Ctx>> FactoryBase<'a, Ctx> for NodeFactory { +impl<'a, Ctx: Context<'a>, F: Factory<'a, Ctx>> FactoryBase<'a, Ctx> for NodeFactory { type Mtbl = Node<'a, Ctx, F::Mtbl>; type ParseError = TreeParseError; @@ -159,29 +154,17 @@ impl<'a, Ctx: Context<'a>, F: Factory<'a, Ctx>> RegularFactory<'a, Ctx> for Node } } -impl<'a, Ctx: Context<'a>, F: FactoryBase<'a, Ctx>> FactoryBase<'a, Ctx> for TreeFactory { +impl<'a, Ctx: Context<'a>, F: Factory<'a, Ctx>> FactoryBase<'a, Ctx> for TreeFactory { type Mtbl = Tree<'a, Ctx, F::Mtbl>; type ParseError = TreeParseError; } impl ParseMode for TreeFactory { - type Mode = RegularMode; + type Mode = InliningMode; } -impl<'a, Ctx: Context<'a>, F: FactoryBase<'a, Ctx>> RegularFactory<'a, Ctx> for TreeFactory { - fn rdeserialize(&self, inctx: impl InCtx<'a, Ctx>) -> ParseResult<'a, Ctx, Self> { - self.ideserialize(inctx).seal() - } - - fn rextend(&self, mut mentionable: Self::Mtbl, tail: &[u8]) -> ParseResult<'a, Ctx, Self> { - mentionable.height = u64::a_extend(mentionable.height, tail)?; - mentionable.validate_height()?; - Ok(mentionable) - } -} - -impl<'a, Ctx: Context<'a>, F: FactoryBase<'a, Ctx>> InlineableFactory<'a, Ctx> for TreeFactory { +impl<'a, Ctx: Context<'a>, F: Factory<'a, Ctx>> InlineableFactory<'a, Ctx> for TreeFactory { fn extension_error(&self, tail: &[u8]) -> Self::ParseError { u64::a_extension_error(tail).into() } diff --git a/src/rstd/inlining.rs b/src/rstd/inlining.rs index c748dd5..adab0a5 100644 --- a/src/rstd/inlining.rs +++ b/src/rstd/inlining.rs @@ -1,5 +1,6 @@ //! Traits to better express parsing semantics. +mod modes; pub mod static_pair; use crate::rcore::*; @@ -9,10 +10,14 @@ use super::{ *, }; +pub use self::modes::InliningMode; + pub type IParseResult<'a, Ctx, F, I> = Result<(Mtbl<'a, Ctx, F>, I), ParseError<'a, Ctx, F>>; /// This factory should return an error on EOF. -pub trait InlineableFactory<'a, Ctx: Context<'a>>: FactoryBase<'a, Ctx> { +pub trait InlineableFactory<'a, Ctx: Context<'a>>: + FactoryBase<'a, Ctx> + ParseMode +{ fn extension_error(&self, tail: &[u8]) -> Self::ParseError; fn ideserialize>(&self, inctx: I) -> IParseResult<'a, Ctx, Self, I>; @@ -48,7 +53,7 @@ pub trait ConstSizeObject<'a, Ctx: Context<'a>>: FixedSizeObject<'a, Ctx> { pub type ADParseResult = Result<(A, D), AParseError>; /// Atomic analogue of [`InlineableFactory`]/[`InlineableObject`]. -pub trait InlineableAtomic: AtomicBase + ParseMode { +pub trait InlineableAtomic: AtomicBase + ParseMode { fn a_extension_error(tail: &[u8]) -> Self::AParseError; fn a_ideserialize(inlining: D) -> ADParseResult; diff --git a/src/rstd/inlining/modes.rs b/src/rstd/inlining/modes.rs new file mode 100644 index 0000000..decb4ac --- /dev/null +++ b/src/rstd/inlining/modes.rs @@ -0,0 +1,33 @@ +use super::*; + +pub struct InliningMode; + +impl<'a, Ctx: Context<'a>, F: InlineableFactory<'a, Ctx>> FactoryProxy<'a, Ctx> + for WithMode +{ + type F = F; + + fn pdeserialize(f: &Self::F, inctx: impl InCtx<'a, Ctx>) -> ParseResult<'a, Ctx, Self::F> { + f.ideserialize(inctx).seal() + } + + fn pextend( + f: &Self::F, + _mentionable: Mtbl<'a, Ctx, Self::F>, + tail: &[u8], + ) -> ParseResult<'a, Ctx, Self::F> { + Err(f.extension_error(tail)) + } +} + +impl AtomicProxy for WithMode { + type A = A; + + fn pa_deserialize(inlining: impl Inlining) -> AParseResult { + A::a_ideserialize(inlining).seal() + } + + fn pa_extend(_a: Self::A, tail: &[u8]) -> AParseResult { + Err(A::a_extension_error(tail)) + } +} diff --git a/src/rstd/inlining/static_pair.rs b/src/rstd/inlining/static_pair.rs index cf89c63..171a68d 100644 --- a/src/rstd/inlining/static_pair.rs +++ b/src/rstd/inlining/static_pair.rs @@ -34,9 +34,9 @@ pub trait StaticPair<'a, Ctx: Context<'a>>: /// [Factory] data. May, depending on the usecase, include factory (factories) on the element(s). type FactoryData: 'a + Send + Sync + Clone; /// First element's type. Must equal [`StaticPairSerializable::SA`]. - type A: Mentionable<'a, Ctx, Fctr = Self::FA>; + type A: MentionableBase<'a, Ctx, Fctr = Self::FA>; /// Second element's type. Must equal [`StaticPairSerializable::SB`]. - type B: Mentionable<'a, Ctx, Fctr = Self::FB>; + type B: MentionableBase<'a, Ctx, Fctr = Self::FB>; /// First element's factory. type FA: Factory<'a, Ctx, Mtbl = Self::A> + InlineableFactory<'a, Ctx>; /// Second element's factory. @@ -100,7 +100,9 @@ impl Serializable for StaticPairObject { } } -impl<'a, Ctx: Context<'a>, SP: StaticPair<'a, Ctx>> Mentionable<'a, Ctx> for StaticPairObject { +impl<'a, Ctx: Context<'a>, SP: StaticPair<'a, Ctx>> MentionableBase<'a, Ctx> + for StaticPairObject +{ type Fctr = StaticPairFactory<'a, Ctx, SP>; fn factory(&self) -> Self::Fctr { @@ -133,11 +135,13 @@ impl<'a, Ctx: Context<'a>, SP: StaticPair<'a, Ctx>> FactoryBase<'a, Ctx> } impl<'a, Ctx: Context<'a>, SP: StaticPair<'a, Ctx>> ParseMode for StaticPairFactory<'a, Ctx, SP> { - type Mode = RegularMode; + type Mode = ::Mode; } impl<'a, Ctx: Context<'a>, SP: StaticPair<'a, Ctx>> RegularFactory<'a, Ctx> for StaticPairFactory<'a, Ctx, SP> +where + SP::FB: RegularFactory<'a, Ctx>, { fn rdeserialize(&self, inctx: impl InCtx<'a, Ctx>) -> ParseResult<'a, Ctx, Self> { let (fa, fb) = SP::factories(&self.factory_data); diff --git a/src/rstd/nullable.rs b/src/rstd/nullable.rs index 438a614..7e08dca 100644 --- a/src/rstd/nullable.rs +++ b/src/rstd/nullable.rs @@ -6,7 +6,7 @@ use crate::rcore::*; use super::{inlining::*, point::*, *}; /// Nullable reference type. Made for use as a linking element in data structures. -pub enum Nullable<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx>> { +pub enum Nullable<'a, Ctx: Context<'a>, A: MentionableBase<'a, Ctx>> { /// Unlike original Python implementation, stores the factory only in the null case. Null(A::Fctr), NotNull(Point<'a, Ctx, A>), @@ -19,7 +19,7 @@ pub struct NullableFactory { factory: F, } -impl<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx>> Serializable for Nullable<'a, Ctx, A> { +impl<'a, Ctx: Context<'a>, A: MentionableBase<'a, Ctx>> Serializable for Nullable<'a, Ctx, A> { fn serialize(&self, serializer: &mut dyn Serializer) { serializer.write(match self { Self::Null(_) => &HASH_ZEROS, @@ -28,7 +28,9 @@ impl<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx>> Serializable for Nullable<'a } } -impl<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx>> Mentionable<'a, Ctx> for Nullable<'a, Ctx, A> { +impl<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx>> MentionableBase<'a, Ctx> + for Nullable<'a, Ctx, A> +{ type Fctr = NullableFactory; fn factory(&self) -> Self::Fctr { @@ -50,24 +52,14 @@ impl<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx>> Mentionable<'a, Ctx> for Nul } } -impl<'a, Ctx: Context<'a>, F: FactoryBase<'a, Ctx>> FactoryBase<'a, Ctx> for NullableFactory { +impl<'a, Ctx: Context<'a>, F: Factory<'a, Ctx>> FactoryBase<'a, Ctx> for NullableFactory { type Mtbl = Nullable<'a, Ctx, F::Mtbl>; type ParseError = PointParseError; } impl ParseMode for NullableFactory { - type Mode = RegularMode; -} - -impl<'a, Ctx: Context<'a>, F: FactoryBase<'a, Ctx>> RegularFactory<'a, Ctx> for NullableFactory { - fn rdeserialize(&self, inctx: impl InCtx<'a, Ctx>) -> ParseResult<'a, Ctx, Self> { - self.ideserialize(inctx).seal() - } - - fn rextend(&self, _mentionable: Self::Mtbl, tail: &[u8]) -> ParseResult<'a, Ctx, Self> { - Err(self.extension_error(tail)) - } + type Mode = InliningMode; } impl<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx>> Nullable<'a, Ctx, Nullable<'a, Ctx, A>> { @@ -102,7 +94,7 @@ impl NullableFactory { } } -impl<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx>> Clone for Nullable<'a, Ctx, A> { +impl<'a, Ctx: Context<'a>, A: MentionableBase<'a, Ctx>> Clone for Nullable<'a, Ctx, A> { fn clone(&self) -> Self { match self { Self::Null(factory) => Self::Null(factory.clone()), @@ -111,9 +103,7 @@ impl<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx>> Clone for Nullable<'a, Ctx, } } -impl<'a, Ctx: Context<'a>, F: FactoryBase<'a, Ctx>> InlineableFactory<'a, Ctx> - for NullableFactory -{ +impl<'a, Ctx: Context<'a>, F: Factory<'a, Ctx>> InlineableFactory<'a, Ctx> for NullableFactory { fn extension_error(&self, tail: &[u8]) -> Self::ParseError { PointParseError::WrongLength(HASH_SIZE + tail.len()) } diff --git a/src/rstd/point.rs b/src/rstd/point.rs index 524805d..2f3f7ee 100644 --- a/src/rstd/point.rs +++ b/src/rstd/point.rs @@ -11,7 +11,7 @@ impl<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx>> Serializable for Point<'a, C } } -impl<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx>> Mentionable<'a, Ctx> for Point<'a, Ctx, A> { +impl<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx>> MentionableBase<'a, Ctx> for Point<'a, Ctx, A> { type Fctr = PointFactory; fn factory(&self) -> Self::Fctr { @@ -69,27 +69,17 @@ impl<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx>> AsRef<[u8]> for Point<'a, Ct } } -impl<'a, Ctx: Context<'a>, F: FactoryBase<'a, Ctx>> FactoryBase<'a, Ctx> for PointFactory { +impl<'a, Ctx: Context<'a>, F: Factory<'a, Ctx>> FactoryBase<'a, Ctx> for PointFactory { type Mtbl = Point<'a, Ctx, F::Mtbl>; type ParseError = PointParseError; } impl ParseMode for PointFactory { - type Mode = RegularMode; + type Mode = InliningMode; } -impl<'a, Ctx: Context<'a>, F: FactoryBase<'a, Ctx>> RegularFactory<'a, Ctx> for PointFactory { - fn rdeserialize(&self, inctx: impl InCtx<'a, Ctx>) -> ParseResult<'a, Ctx, Self> { - self.ideserialize(inctx).seal() - } - - fn rextend(&self, _mentionable: Self::Mtbl, tail: &[u8]) -> ParseResult<'a, Ctx, Self> { - Err(self.extension_error(tail)) - } -} - -impl<'a, Ctx: Context<'a>, F: FactoryBase<'a, Ctx>> InlineableFactory<'a, Ctx> for PointFactory { +impl<'a, Ctx: Context<'a>, F: Factory<'a, Ctx>> InlineableFactory<'a, Ctx> for PointFactory { fn extension_error(&self, tail: &[u8]) -> Self::ParseError { PointParseError::WrongLength(HASH_SIZE + tail.len()) } diff --git a/src/rstd/typeless.rs b/src/rstd/typeless.rs index 72a163e..aadd518 100644 --- a/src/rstd/typeless.rs +++ b/src/rstd/typeless.rs @@ -48,7 +48,7 @@ impl<'a, Ctx: Context<'a>> Serializable for TypelessMentionable<'a, Ctx> { } } -impl<'a, Ctx: Context<'a>> Mentionable<'a, Ctx> for TypelessMentionable<'a, Ctx> { +impl<'a, Ctx: Context<'a>> MentionableBase<'a, Ctx> for TypelessMentionable<'a, Ctx> { type Fctr = TypelessFactory<'a, Ctx>; fn factory(&self) -> Self::Fctr { @@ -207,7 +207,7 @@ where pub trait MentionableExt<'a, Ctx: Context<'a>>: Mentionable<'a, Ctx> { /// References ([Point]s) to other objects. Typeless. fn points_typeless(&self, points: &mut Vec>>); - /// [Vec] of [Point]s as used by [`Mentionable::topology`]. + /// [Vec] of [Point]s as used by [`MentionableBase::topology`]. fn points_vec(&self) -> Vec>>; }