From c20df8108b7ac9ae2feb0a4c540e2aa4e92aaad0 Mon Sep 17 00:00:00 2001 From: timofey Date: Sun, 14 May 2023 10:26:40 +0000 Subject: [PATCH] refactor `cast` --- src/std/cast.rs | 179 +++++++++++++++++++++++++++++++++--------------- 1 file changed, 123 insertions(+), 56 deletions(-) diff --git a/src/std/cast.rs b/src/std/cast.rs index 332215f..3ee8ef3 100644 --- a/src/std/cast.rs +++ b/src/std/cast.rs @@ -60,44 +60,90 @@ impl<'a> Display for CastError<'a> { } } +impl<'a> CastError<'a> { + fn pure(self) -> HashResolution<'a, Ctx> + where + Ctx::LookupError<'a>: From>, + { + Ctx::T::pure(Err(self.into())) + } +} + +impl<'a, Ctx: 'a + Context> CastResolver<'a, Ctx> { + fn rc(points: Vec>>) -> Rc> + where + Ctx::LookupError<'a>: From>, + { + Rc::new(Self { points }) + } + + fn _get_point( + &self, + index: usize, + ) -> Result<&Point<'a, Ctx, TypelessMentionable<'a, Ctx>>, CastError<'a>> { + match self.points.get(index) { + Some(point) => Ok(point), + None => Err(CastError::AddressIndexOutOfBounds { + index, + length: self.points.len(), + }), + } + } + + fn _validate_point( + &self, + point: &Point<'a, Ctx, TypelessMentionable<'a, Ctx>>, + address: Address, + ) -> Result<(), CastError<'a>> { + if point.point == address.point { + Ok(()) + } else { + Err(CastError::AddressPointMismatch { + expected: point.point, + received: address.point, + index: address.index, + }) + } + } + + fn get_point( + &self, + address: Address, + ) -> Result<&Point<'a, Ctx, TypelessMentionable<'a, Ctx>>, CastError<'a>> { + let point = self._get_point(address.index)?; + self._validate_point(point, address)?; + Ok(point) + } +} + +fn cast_resolved<'a, Ctx: 'a + Context>( + resolved: ResolutionResult<'a, Ctx, TypelessMentionable<'a, Ctx>>, +) -> HashResolutionResult<'a, Ctx> +where + Ctx::LookupError<'a>: From>, +{ + match resolved { + Ok(mentionable) => Ok(( + mentionable.bytes(), + CastResolver::rc(mentionable.points_vec()), + )), + Err(error) => Err(match error { + ResolutionError::Lookup(lookup_error) => lookup_error, + ResolutionError::Parse(parse_error) => CastError::Typeless(parse_error).into(), + }), + } +} + impl<'a, Ctx: 'a + Context> Resolver<'a, Ctx> for CastResolver<'a, Ctx> where Ctx::LookupError<'a>: From>, { fn resolve(self: Rc, address: Address) -> HashResolution<'a, Ctx> { - let point = match self.points.get(address.index) { - Some(point) => point, - None => { - return Ctx::T::pure(Err(CastError::AddressIndexOutOfBounds { - index: address.index, - length: self.points.len(), - } - .into())); - } + let point = match self.get_point(address) { + Ok(point) => point, + Err(cast_error) => return cast_error.pure::(), }; - if point.point != address.point { - return Ctx::T::pure(Err(CastError::AddressPointMismatch { - expected: point.point, - received: address.point, - index: address.index, - } - .into())); - } - Ctx::T::fmap( - |resolved| match resolved { - Ok(mentionable) => { - let resolver: Rc> = Rc::new(CastResolver { - points: mentionable.points_vec(), - }); - Ok((mentionable.bytes(), resolver)) - } - Err(error) => Err(match error { - ResolutionError::Lookup(lookup_error) => lookup_error, - ResolutionError::Parse(parse_error) => CastError::Typeless(parse_error).into(), - }), - }, - point.resolve(), - ) + Ctx::T::fmap(cast_resolved, point.resolve()) } } @@ -116,9 +162,7 @@ where ) -> CastResult<'a, Ctx, A> { factory.parse_slice( &self.bytes(), - map_resolver(Rc::new(CastResolver { - points: self.points_vec(), - })), + map_resolver(CastResolver::rc(self.points_vec())), ) } @@ -128,34 +172,57 @@ where } } -impl<'a, Ctx: Context> Point<'a, Ctx, TypelessMentionable<'a, Ctx>> +fn cast_resolve<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>>( + typeless_origin: Rc>>, + factory: A::Fctr, +) -> Resolution<'a, Ctx, A> where Ctx::LookupError<'a>: From>, { + Ctx::T::fmap( + move |resolved| match resolved { + Ok(typeless_mentionable) => match typeless_mentionable.cast(factory) { + Ok(mentionable) => Ok(Rc::new(mentionable)), + Err(parse_error) => Err(ResolutionError::Parse(parse_error)), + }, + Err(error) => Err(ResolutionError::Lookup(match error { + ResolutionError::Lookup(lookup_error) => lookup_error, + ResolutionError::Parse(parse_error) => CastError::Typeless(parse_error).into(), + })), + }, + typeless_origin.clone().resolve(), + ) +} + +fn cast_origin<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>>( + typeless_origin: Rc>>, + factory: A::Fctr, +) -> Rc> +where + Ctx::LookupError<'a>: From>, +{ + wrapped_origin(factory.clone(), move || { + cast_resolve(typeless_origin.clone(), factory.clone()) + }) +} + +impl<'a, Ctx: 'a + Context> Point<'a, Ctx, TypelessMentionable<'a, Ctx>> +where + Ctx::LookupError<'a>: From>, +{ + fn cast_origin>( + &self, + factory: A::Fctr, + ) -> Rc> { + let typeless_origin = self.origin.clone(); + cast_origin(typeless_origin, factory) + } + /// See [`TypelessMentionable::cast`] pub fn cast>(&self, factory: A::Fctr) -> Point<'a, Ctx, A> { - let typeless_origin = self.origin.clone(); - let origin: Rc> = wrapped_origin(factory.clone(), move || { - let factory = factory.clone(); - Ctx::T::fmap( - move |resolved| match resolved { - Ok(typeless_mentionable) => match typeless_mentionable.cast(factory) { - Ok(mentionable) => Ok(Rc::new(mentionable)), - Err(parse_error) => Err(ResolutionError::Parse(parse_error)), - }, - Err(error) => Err(ResolutionError::Lookup(match error { - ResolutionError::Lookup(lookup_error) => lookup_error, - ResolutionError::Parse(parse_error) => { - CastError::Typeless(parse_error).into() - } - })), - }, - typeless_origin.clone().resolve(), - ) - }); Point { point: self.point, - origin, + origin: self.cast_origin(factory), } } }