diff --git a/src/core.rs b/src/core.rs index 4a4af40..76311ef 100644 --- a/src/core.rs +++ b/src/core.rs @@ -2,7 +2,7 @@ //! Brings [`Mentionable`]/[`Factory`]/[`Origin`] concepts from the original implementation in Python. //! Allows for more generic behaviour via [`Context`], as opposed to original async-only. -use std::{error::Error, fmt::Display, rc::Rc}; +use std::{cmp::min, error::Error, fmt::Display, rc::Rc}; use crate::func::*; @@ -155,6 +155,7 @@ pub trait Factory<'a, Ctx: 'a + Context>: Clone + 'a { &self, deserializer: &mut dyn Deserializer, resolver: Rc>, + addresses: &mut Addresses, ) -> ParseResult<'a, Ctx, Self>; /// Called by finite stream parsers if there's any data left. fn unexpected_tail(&self, tail: &[u8]) -> Self::ParseError; @@ -231,6 +232,22 @@ impl<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> Point<'a, Ctx, A> { LocalOrigin::from(mentionable), ) } + + /// Make a [Point] from an [Address]. + pub fn from_address( + address: Address, + factory: A::Fctr, + resolver: Rc>, + ) -> Self { + Point { + point: address.point, + origin: Rc::new(ResolverOrigin { + r_factory: factory, + r_address: address, + r_resolver: resolver, + }), + } + } } impl<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> From for Point<'a, Ctx, A> { @@ -251,8 +268,8 @@ pub struct TypelessMentionable<'a, Ctx: 'a + Context> { type TypelessParsed<'a, Ctx> = Result, Box>; -type TypelessDeserialize<'a, Ctx> = - dyn 'a + Fn(&mut dyn Deserializer, Rc>) -> TypelessParsed<'a, Ctx>; +type TypelessDeserialize<'a, Ctx> = dyn 'a + + Fn(&mut dyn Deserializer, Rc>, &mut Addresses) -> TypelessParsed<'a, Ctx>; type TypelessUnexpectedTail<'a> = dyn 'a + Fn(&[u8]) -> TypelessError<'a>; @@ -318,8 +335,9 @@ impl<'a, Ctx: 'a + Context> Factory<'a, Ctx> for TypelessFactory<'a, Ctx> { &self, deserializer: &mut dyn Deserializer, resolver: Rc>, + addresses: &mut Addresses, ) -> ParseResult<'a, Ctx, Self> { - match (self.t_deserialize)(deserializer, resolver) { + match (self.t_deserialize)(deserializer, resolver, addresses) { Ok(mentionable) => Ok(mentionable), Err(error) => Err(TypelessError(error)), } @@ -348,8 +366,8 @@ impl<'a, Ctx: 'a + Context> TypelessFactory<'a, Ctx> { pub fn from_typed>(factory: F) -> Self { let tail_factory = factory.clone(); TypelessFactory { - t_deserialize: Rc::new(move |deserializer, resolver| { - match factory.deserialize(deserializer, resolver) { + t_deserialize: Rc::new(move |deserializer, resolver, addresses| { + match factory.deserialize(deserializer, resolver, addresses) { Ok(mentionable) => Ok(TypelessMentionable::from_typed(Rc::new(mentionable))), Err(error) => Err(Box::new(error)), } @@ -366,3 +384,158 @@ impl<'a> TypelessError<'a> { TypelessError(Box::new(error)) } } + +/// Preferred way to parse [Point]s off of a [Serializer]. +pub struct Addresses { + current: usize, +} + +impl Addresses { + /// Read the next [Address]. + pub fn next<'a>( + &mut self, + deserializer: &'a mut dyn Deserializer, + ) -> Result { + let point = deserializer.read_n_const::()?; + let address = Address { + point, + index: self.current, + }; + self.current += 1; + Ok(address) + } + + /// Read the next [Point]. + pub fn next_point<'a, 'b, Ctx: 'a + Context, A: Mentionable<'a, Ctx>>( + &mut self, + deserializer: &'b mut dyn Deserializer, + resolver: Rc>, + factory: A::Fctr, + ) -> Result, &'b [u8]> { + Ok(Point::from_address( + self.next(deserializer)?, + factory, + resolver, + )) + } + + /// Start reading the [Address]es. + fn start() -> Self { + Addresses { current: 0 } + } +} + +pub trait ExtDeserializer { + fn read_n_const(&mut self) -> Result<[u8; N], &[u8]>; +} + +impl ExtDeserializer for D { + fn read_n_const(&mut self) -> Result<[u8; N], &[u8]> { + let slice = self.read_n(N); + match slice.try_into() { + Ok(array) => Ok(array), + Err(_) => Err(slice), + } + } +} + +struct ResolverOrigin<'a, Ctx: 'a + Context, F: Factory<'a, Ctx>> { + r_factory: F, + r_address: Address, + r_resolver: Rc>, +} + +fn _resolve_origin<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>>( + origin: Rc>, +) -> Resolution<'a, Ctx, A> { + let resolution = origin.r_resolver.clone().resolve(origin.r_address); + Ctx::T::fmap( + move |resolved| match resolved { + Ok((src, resolver)) => match origin.r_factory.parse_slice(&src, resolver) { + Ok(mentionable) => Ok(Rc::new(mentionable)), + Err(parse_error) => Err(ResolutionError::Parse(parse_error)), + }, + Err(lookup_error) => Err(ResolutionError::Lookup(lookup_error)), + }, + resolution, + ) +} + +impl<'a, Ctx: 'a + Context, F: Factory<'a, Ctx>> Origin<'a, Ctx> for ResolverOrigin<'a, Ctx, F> { + type Mtbl = F::Mtbl; + + fn factory(&self) -> >::Fctr { + self.r_factory.clone() + } + + fn resolve(self: Rc) -> Resolution<'a, Ctx, Self::Mtbl> { + _resolve_origin(self) + } +} + +fn _parse_slice<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>>( + factory: &A::Fctr, + slice: &[u8], + resolver: Rc>, +) -> ParseResult<'a, Ctx, A::Fctr> { + let mut deserializer = SliceDeserializer::from(slice); + let mentionable = factory.deserialize(&mut deserializer, resolver, &mut Addresses::start())?; + let tail = deserializer.read_all(); + if tail.is_empty() { + Ok(mentionable) + } else { + Err(factory.unexpected_tail(tail)) + } +} + +pub trait ExtFactory<'a, Ctx: 'a + Context>: Factory<'a, Ctx> { + fn parse_slice( + &self, + slice: &[u8], + resolver: Rc>, + ) -> ParseResult<'a, Ctx, Self>; +} + +impl<'a, Ctx: 'a + Context, F: Factory<'a, Ctx>> ExtFactory<'a, Ctx> for F { + fn parse_slice( + &self, + slice: &[u8], + resolver: Rc>, + ) -> ParseResult<'a, Ctx, Self> { + _parse_slice::(self, slice, resolver) + } +} + +pub struct SliceDeserializer<'a> { + slice: &'a [u8], + pos: usize, +} + +impl<'a> From<&'a [u8]> for SliceDeserializer<'a> { + fn from(value: &'a [u8]) -> Self { + SliceDeserializer { + slice: value, + pos: 0, + } + } +} + +impl<'a> Deserializer for SliceDeserializer<'a> { + fn read_n(&mut self, n: usize) -> &[u8] { + let (left, right) = self.slice.split_at(min(n, self.slice.len())); + self.slice = right; + self.pos += left.len(); + left + } + + fn read_all(&mut self) -> &[u8] { + let left = self.slice; + self.slice = &[]; + self.pos += left.len(); + left + } + + fn tell(&self) -> usize { + self.pos + } +} diff --git a/src/std.rs b/src/std.rs index 34a9186..fccc07b 100644 --- a/src/std.rs +++ b/src/std.rs @@ -1,10 +1,11 @@ +//! Standard extensions to [`crate::core`]. + pub mod atomic; pub mod cast; pub mod collections; pub mod inlining; pub mod nullable; -use std::cmp::min; use std::{error::Error, fmt::Display, rc::Rc}; use crate::core::*; @@ -161,62 +162,12 @@ impl From<&[u8]> for PointParseError { } } -impl<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> Point<'a, Ctx, A> { - fn from_address( - address: Address, - factory: A::Fctr, - resolver: Rc>, - ) -> Self { - Point { - point: address.point, - origin: Rc::new(ResolverOrigin { - r_factory: factory, - r_address: address, - r_resolver: resolver, - }), - } - } -} - impl<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> AsRef<[u8]> for Point<'a, Ctx, A> { fn as_ref(&self) -> &[u8] { &self.point } } -pub struct Addresses { - current: usize, -} - -impl Addresses { - fn next<'a>(&mut self, deserializer: &'a mut dyn Deserializer) -> Result { - let point = deserializer.read_n_const::()?; - let address = Address { - point, - index: self.current, - }; - self.current += 1; - Ok(address) - } - - fn next_point<'a, 'b, Ctx: 'a + Context, A: Mentionable<'a, Ctx>>( - &mut self, - deserializer: &'b mut dyn Deserializer, - resolver: Rc>, - factory: A::Fctr, - ) -> Result, &'b [u8]> { - Ok(Point::from_address( - self.next(deserializer)?, - factory, - resolver, - )) - } - - fn start() -> Self { - Addresses { current: 0 } - } -} - impl<'a, Ctx: 'a + Context, F: Factory<'a, Ctx>> Factory<'a, Ctx> for PointFactory { type Mtbl = Point<'a, Ctx, F::Mtbl>; @@ -226,8 +177,8 @@ impl<'a, Ctx: 'a + Context, F: Factory<'a, Ctx>> Factory<'a, Ctx> for PointFacto &self, deserializer: &mut dyn Deserializer, resolver: Rc>, + addresses: &mut Addresses, ) -> ParseResult<'a, Ctx, Self> { - let mut addresses = Addresses::start(); Ok(addresses.next_point(deserializer, resolver, self.factory.clone())?) } @@ -236,121 +187,6 @@ impl<'a, Ctx: 'a + Context, F: Factory<'a, Ctx>> Factory<'a, Ctx> for PointFacto } } -struct ResolverOrigin<'a, Ctx: 'a + Context, F: Factory<'a, Ctx>> { - r_factory: F, - r_address: Address, - r_resolver: Rc>, -} - -fn _resolve_origin<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>>( - origin: Rc>, -) -> Resolution<'a, Ctx, A> { - let resolution = origin.r_resolver.clone().resolve(origin.r_address); - Ctx::T::fmap( - move |resolved| match resolved { - Ok((src, resolver)) => match origin.r_factory.parse_slice(&src, resolver) { - Ok(mentionable) => Ok(Rc::new(mentionable)), - Err(parse_error) => Err(ResolutionError::Parse(parse_error)), - }, - Err(lookup_error) => Err(ResolutionError::Lookup(lookup_error)), - }, - resolution, - ) -} - -impl<'a, Ctx: 'a + Context, F: Factory<'a, Ctx>> Origin<'a, Ctx> for ResolverOrigin<'a, Ctx, F> { - type Mtbl = F::Mtbl; - - fn factory(&self) -> >::Fctr { - self.r_factory.clone() - } - - fn resolve(self: Rc) -> Resolution<'a, Ctx, Self::Mtbl> { - _resolve_origin(self) - } -} - -struct SliceDeserializer<'a> { - slice: &'a [u8], - pos: usize, -} - -impl<'a> From<&'a [u8]> for SliceDeserializer<'a> { - fn from(value: &'a [u8]) -> Self { - SliceDeserializer { - slice: value, - pos: 0, - } - } -} - -impl<'a> Deserializer for SliceDeserializer<'a> { - fn read_n(&mut self, n: usize) -> &[u8] { - let (left, right) = self.slice.split_at(min(n, self.slice.len())); - self.slice = right; - self.pos += left.len(); - left - } - - fn read_all(&mut self) -> &[u8] { - let left = self.slice; - self.slice = &[]; - self.pos += left.len(); - left - } - - fn tell(&self) -> usize { - self.pos - } -} - -fn _parse_slice<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>>( - factory: &A::Fctr, - slice: &[u8], - resolver: Rc>, -) -> ParseResult<'a, Ctx, A::Fctr> { - let mut deserializer = SliceDeserializer::from(slice); - let mentionable = factory.deserialize(&mut deserializer, resolver)?; - let tail = deserializer.read_all(); - if tail.is_empty() { - Ok(mentionable) - } else { - Err(factory.unexpected_tail(tail)) - } -} - -pub trait ExtFactory<'a, Ctx: 'a + Context>: Factory<'a, Ctx> { - fn parse_slice( - &self, - slice: &[u8], - resolver: Rc>, - ) -> ParseResult<'a, Ctx, Self>; -} - -impl<'a, Ctx: 'a + Context, F: Factory<'a, Ctx>> ExtFactory<'a, Ctx> for F { - fn parse_slice( - &self, - slice: &[u8], - resolver: Rc>, - ) -> ParseResult<'a, Ctx, Self> { - _parse_slice::(self, slice, resolver) - } -} - -pub trait ExtDeserializer { - fn read_n_const(&mut self) -> Result<[u8; N], &[u8]>; -} - -impl ExtDeserializer for D { - fn read_n_const(&mut self) -> Result<[u8; N], &[u8]> { - let slice = self.read_n(N); - match slice.try_into() { - Ok(array) => Ok(array), - Err(_) => Err(slice), - } - } -} - impl Display for Address { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.write_fmt(format_args!("{}@{}", hex::encode(self.point), self.index)) diff --git a/src/std/atomic/atomic_object.rs b/src/std/atomic/atomic_object.rs index a19ac5b..17c13be 100644 --- a/src/std/atomic/atomic_object.rs +++ b/src/std/atomic/atomic_object.rs @@ -1,7 +1,10 @@ +//! Provides [Atomic]-[Mentionable] interface. + use std::ops::Deref; use super::*; +/// Generic implementation of a [Mentionable] for [Atomic]s. pub struct AtomicObject { atomic: A, } @@ -46,12 +49,14 @@ impl<'a, Ctx: 'a + Context, A: Atomic> Mentionable<'a, Ctx> for AtomicObject fn points(&self, _points: &mut Vec>>) {} } -/// Generic implementation of a factory for [Atomic]s. -pub struct AtomicFactory(PhantomData); +/// Generic implementation of a [Factory] for [Atomic]s. +pub struct AtomicFactory { + _pd: PhantomData, +} impl AtomicFactory { fn new() -> Self { - AtomicFactory(PhantomData) + AtomicFactory { _pd: PhantomData } } } @@ -70,6 +75,7 @@ impl<'a, Ctx: 'a + Context, A: Atomic> Factory<'a, Ctx> for AtomicFactory { &self, deserializer: &mut dyn Deserializer, _resolver: Rc>, + _addresses: &mut Addresses, ) -> ParseResult<'a, Ctx, Self> { Ok(A::deserialize(deserializer)?.into()) } diff --git a/src/std/collections/pair.rs b/src/std/collections/pair.rs index 3127b68..9002412 100644 --- a/src/std/collections/pair.rs +++ b/src/std/collections/pair.rs @@ -1,3 +1,5 @@ +//! [`Pair`] implementation based on [`StaticPair`]. + use std::error::Error; use std::fmt::Display; @@ -18,7 +20,7 @@ impl StaticPairSerializable for Pair { type SA = A; type SB = B; - fn s_elements(&self) -> (&Self::SA, &Self::SB) { + fn elements(&self) -> (&Self::SA, &Self::SB) { (&self.a, &self.b) } } @@ -89,8 +91,4 @@ where 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 5708189..ec22a8b 100644 --- a/src/std/collections/stack.rs +++ b/src/std/collections/stack.rs @@ -88,16 +88,23 @@ impl<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> Factory<'a, Ctx> &self, deserializer: &mut dyn Deserializer, resolver: Rc>, + addresses: &mut Addresses, ) -> ParseResult<'a, Ctx, Self> { - let rest = - match NullableFactory::new(self.clone()).deserialize(deserializer, resolver.clone()) { - Ok(rest) => rest, - Err(ppe) => { - return Err(StackParseError::Point(ppe)); - } - }; + let rest = match NullableFactory::new(self.clone()).deserialize( + deserializer, + resolver.clone(), + addresses, + ) { + Ok(rest) => rest, + Err(ppe) => { + return Err(StackParseError::Point(ppe)); + } + }; let element = Rc::new( - match self.element_factory.deserialize(deserializer, resolver) { + match self + .element_factory + .deserialize(deserializer, resolver, addresses) + { Ok(element) => element, Err(epe) => { return Err(StackParseError::Element(epe)); diff --git a/src/std/inlining.rs b/src/std/inlining.rs index 548f9d5..655918c 100644 --- a/src/std/inlining.rs +++ b/src/std/inlining.rs @@ -1,3 +1,5 @@ +//! Traits to better express parsing semantics. + pub mod static_pair; use super::atomic::atomic_object::*; @@ -5,28 +7,44 @@ use super::atomic::*; use crate::core::*; use crate::std::*; +/// This factory should return an error on EOF. pub trait InlineableFactory {} +/// This factory always reads the same amount of bytes or returns error. pub trait FixedSizeFactory: InlineableFactory { + /// For [`ConstSizeFactory`] this must return [`ConstSizeFactory::SIZE`]. fn size(&self) -> usize; } +/// Compile-time analogue of [`FixedSizeFactory`]. pub trait ConstSizeFactory: FixedSizeFactory { + /// Must be equal to [`FixedSizeFactory::size()`]. const SIZE: usize; } +/// Object analogue of [`InlineableFactory`]. pub trait InlineableObject<'a, Ctx: 'a + Context>: 'a {} +/// Object analogue of [`FixedSizeFactory`]. pub trait FixedSizeObject<'a, Ctx: 'a + Context>: InlineableObject<'a, Ctx> { + /// For [`ConstSizeObject`] this must return [`ConstSizeObject::SIZE`]. fn size(&self) -> usize; } +/// Object analogue of [`ConstSizeFactory`]. pub trait ConstSizeObject<'a, Ctx: 'a + Context>: FixedSizeObject<'a, Ctx> { + /// Must be equal to [`FixedSizeObject::size()`]. const SIZE: usize; } +/// Atomic analogue of [`InlineableFactory`]/[`InlineableObject`]. pub trait InlineableAtomic {} +/// Atomic analogue of [`ConstSizeFactory`]/[`ConstSizeObject`]. +/// +/// Note: `FixedSizeAtomic` doesn't exist because it would +/// either be const anyway +/// or have a very undesireable implementation. pub trait ConstSizeAtomic: InlineableAtomic { const SIZE: usize; } @@ -64,6 +82,7 @@ where const SIZE: usize = A::Fctr::SIZE; } +/// Error returned by [`CheckedParse::deserialize_checked`]/[`CheckedSerialize::serialize_checked`]. #[derive(Debug)] pub struct SizeError { expected: usize, @@ -81,6 +100,7 @@ impl Display for SizeError { impl Error for SizeError {} +/// Wrapper for [`SizeError`]/[`Factory::ParseError`]. #[derive(Debug)] pub enum CheckedParseError { Parse(P), @@ -104,18 +124,24 @@ impl From

for CheckedParseError

{ } } +/// Returned by [`CheckedParse::deserialize_checked`]. pub type CheckedParseResult<'a, Ctx, F> = Result<>::Mtbl, CheckedParseError<>::ParseError>>; +/// Extension trait for factories that ensures fixed size read. pub trait CheckedParse<'a, Ctx: 'a + Context>: FixedSizeFactory + Factory<'a, Ctx> { + /// Verify proper read length using [`Deserializer::tell`]. fn deserialize_checked( &self, deserializer: &mut dyn Deserializer, resolver: Rc>, + addresses: &mut Addresses, ) -> CheckedParseResult<'a, Ctx, Self>; } +/// Extension trait for factories that ensures fixed size write. pub trait CheckedSerialize<'a, Ctx: 'a + Context>: Serializable + FixedSizeObject<'a, Ctx> { + /// Verify proper write length using [`Serializer::tell`]. fn serialize_checked(&self, serializer: &mut dyn Serializer) -> Result<(), SizeError>; } @@ -124,10 +150,11 @@ impl<'a, Ctx: 'a + Context, F: FixedSizeFactory + Factory<'a, Ctx>> CheckedParse &self, deserializer: &mut dyn Deserializer, resolver: Rc>, + addresses: &mut Addresses, ) -> CheckedParseResult<'a, Ctx, Self> { let expected_size = self.size(); let start = deserializer.tell(); - let result = self.deserialize(deserializer, resolver)?; + let result = self.deserialize(deserializer, resolver, addresses)?; let end = deserializer.tell(); let received_size = end - start; if received_size == expected_size { @@ -161,6 +188,9 @@ impl<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx> + FixedSizeObject<'a, Ctx>> } } +/// Trait useful for objects which aren't influenced by +/// whether some other type (for example, a generic parameter type) +/// is fixed-size or not. pub trait AlwaysFixedSize { fn _size(&self) -> usize; } @@ -173,6 +203,7 @@ impl FixedSizeFactory for F { } } +/// Compile-time analogue of [`AlwaysFixedSize`]. pub trait AlwaysConstSize { const _SIZE: usize; } diff --git a/src/std/inlining/static_pair.rs b/src/std/inlining/static_pair.rs index 49479a0..0670e96 100644 --- a/src/std/inlining/static_pair.rs +++ b/src/std/inlining/static_pair.rs @@ -1,39 +1,66 @@ +//! Generic implementation for objects that are structured +//! like a pair of two other objects. + use std::ops::Deref; use super::*; use crate::core::*; +/// Trait to represent serialisation of object's data. +/// Due to serialisation being [Context]-free in RADN, +/// this functionality is in a separate trait. pub trait StaticPairSerializable { + /// First element's type. Must equal [`StaticPair::A`]. type SA: Serializable; + /// Second element's type. Must equal [`StaticPair::B`]. type SB: Serializable; - fn s_elements(&self) -> (&Self::SA, &Self::SB); + /// Borrow both elements. + fn elements(&self) -> (&Self::SA, &Self::SB); } +/// Trait to be implemented on object data. +/// +/// [`StaticPair::FA`]/[`StaticPair::FB`] are required members +/// for clarity and [`StaticPair`]'s simpler implementation +/// at the cost of having to specify two extra fields. +/// +/// Note: [`StaticPair::FA`] requires [`InlineableFactory`] be implemented. pub trait StaticPair<'a, Ctx: 'a + Context>: 'a + StaticPairSerializable { + /// [Factory] data. May, depending on the usecase, include factory (factories) on the element(s). type FactoryData: 'a + Clone; + /// First element's type. Must equal [`StaticPairSerializable::SA`]. type A: Mentionable<'a, Ctx, Fctr = Self::FA>; + /// Second element's type. Must equal [`StaticPairSerializable::SB`]. type B: Mentionable<'a, Ctx, Fctr = Self::FB>; + /// First element's factory. type FA: Factory<'a, Ctx, Mtbl = Self::A> + InlineableFactory; + /// Second element's factory. type FB: Factory<'a, Ctx, Mtbl = Self::B>; + /// See [Factory::ParseError]. type ParseError: 'a + Error; + /// Borrow both elements' factories. fn factories(factory_data: &Self::FactoryData) -> (&Self::FA, &Self::FB); + /// Construct the object from the elements. fn from_parsed(factory_data: &Self::FactoryData, a: Self::A, b: Self::B) -> Self; + /// Regularise the error returned while parsing the first element. fn from_error_a( factory_data: &Self::FactoryData, error: >::ParseError, ) -> Self::ParseError; + /// Regularise the error returned while parsing the second element. fn from_error_b( factory_data: &Self::FactoryData, error: >::ParseError, ) -> Self::ParseError; + /// Derive factory data from the object data. fn factory_data(&self) -> Self::FactoryData; - fn elements(&self) -> (&Self::A, &Self::B); } +/// Generic implementation of a [Mentionable] for [StaticPair]s. pub struct StaticPairObject { pair: SP, } @@ -58,13 +85,14 @@ impl Deref for StaticPairObject { } } +/// Generic implementation of a [Factory] for [StaticPair]s. 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(); + let (a, b) = self.pair.elements(); a.serialize(serializer); b.serialize(serializer); } @@ -105,13 +133,14 @@ impl<'a, Ctx: 'a + Context, SP: StaticPair<'a, Ctx>> Factory<'a, Ctx> &self, deserializer: &mut dyn Deserializer, resolver: Rc>, + addresses: &mut Addresses, ) -> ParseResult<'a, Ctx, Self> { let (fa, fb) = SP::factories(&self.factory_data); - let a: SP::A = match fa.deserialize(deserializer, resolver.clone()) { + let a: SP::A = match fa.deserialize(deserializer, resolver.clone(), addresses) { Ok(a) => a, Err(error) => return Err(SP::from_error_a(&self.factory_data, error)), }; - let b: SP::B = match fb.deserialize(deserializer, resolver) { + let b: SP::B = match fb.deserialize(deserializer, resolver, addresses) { Ok(b) => b, Err(error) => return Err(SP::from_error_b(&self.factory_data, error)), }; diff --git a/src/std/nullable.rs b/src/std/nullable.rs index c8fe0cc..7750484 100644 --- a/src/std/nullable.rs +++ b/src/std/nullable.rs @@ -67,8 +67,8 @@ impl<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> Factory<'a, Ctx> &self, deserializer: &mut dyn Deserializer, resolver: std::rc::Rc>, + addresses: &mut Addresses, ) -> ParseResult<'a, Ctx, Self> { - let mut addresses = Addresses::start(); let factory = self.factory.clone(); let address = addresses.next(deserializer)?; Ok(if address.point == HASH_ZEROS {