//! Generic implementation for objects that are structured //! like a pair of two other objects. use std::ops::Deref; use crate::std::*; use super::*; /// 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; /// 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 + Send + Sync + 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; } /// Generic implementation of a [Mentionable] for [StaticPair]s. pub struct StaticPairObject { pair: SP, } impl From for StaticPairObject { fn from(value: SP) -> Self { StaticPairObject { pair: value } } } impl AsRef for StaticPairObject { fn as_ref(&self) -> &SP { &self.pair } } impl Deref for StaticPairObject { type Target = SP; fn deref(&self) -> &Self::Target { &self.pair } } /// 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.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_typed(&self, points: &mut impl TakesPoints<'a, Ctx>) { let (a, b) = self.pair.elements(); a.points_typed(points); b.points_typed(points); } } 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>, 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(), 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, addresses) { 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; }