Point::cast
This commit is contained in:
		
							parent
							
								
									eb153d6396
								
							
						
					
					
						commit
						e40ea67e21
					
				
							
								
								
									
										18
									
								
								src/std.rs
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								src/std.rs
									
									
									
									
									
								
							| @ -15,6 +15,16 @@ struct WrappedOrigin<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> { | |||||||
|     w_resolve: Box<dyn 'a + Fn() -> Resolution<'a, Ctx, A>>, |     w_resolve: Box<dyn 'a + Fn() -> Resolution<'a, Ctx, A>>, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | fn wrapped_origin<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>>( | ||||||
|  |     factory: A::Fctr, | ||||||
|  |     resolve: impl 'a + Fn() -> Resolution<'a, Ctx, A>, | ||||||
|  | ) -> Rc<dyn Origin<'a, Ctx, Mtbl = A>> { | ||||||
|  |     Rc::new(WrappedOrigin { | ||||||
|  |         w_factory: factory, | ||||||
|  |         w_resolve: Box::new(resolve), | ||||||
|  |     }) | ||||||
|  | } | ||||||
|  | 
 | ||||||
| trait MappableOrigin<'a, Ctx: 'a + Context>: Origin<'a, Ctx> { | trait MappableOrigin<'a, Ctx: 'a + Context>: Origin<'a, Ctx> { | ||||||
|     fn map<B: Mentionable<'a, Ctx>>( |     fn map<B: Mentionable<'a, Ctx>>( | ||||||
|         self: Rc<Self>, |         self: Rc<Self>, | ||||||
| @ -152,7 +162,11 @@ impl From<&[u8]> for PointParseError { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> Point<'a, Ctx, A> { | impl<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> Point<'a, Ctx, A> { | ||||||
|     fn from_point(address: Address, factory: A::Fctr, resolver: Rc<dyn Resolver<'a, Ctx>>) -> Self { |     fn from_address( | ||||||
|  |         address: Address, | ||||||
|  |         factory: A::Fctr, | ||||||
|  |         resolver: Rc<dyn Resolver<'a, Ctx>>, | ||||||
|  |     ) -> Self { | ||||||
|         Point { |         Point { | ||||||
|             point: address.point, |             point: address.point, | ||||||
|             origin: Rc::new(ResolverOrigin { |             origin: Rc::new(ResolverOrigin { | ||||||
| @ -191,7 +205,7 @@ impl Addresses { | |||||||
|         resolver: Rc<dyn Resolver<'a, Ctx>>, |         resolver: Rc<dyn Resolver<'a, Ctx>>, | ||||||
|         factory: A::Fctr, |         factory: A::Fctr, | ||||||
|     ) -> Result<Point<'a, Ctx, A>, &'b [u8]> { |     ) -> Result<Point<'a, Ctx, A>, &'b [u8]> { | ||||||
|         Ok(Point::from_point( |         Ok(Point::from_address( | ||||||
|             self.next(deserializer)?, |             self.next(deserializer)?, | ||||||
|             factory, |             factory, | ||||||
|             resolver, |             resolver, | ||||||
|  | |||||||
| @ -79,8 +79,11 @@ fn _parse_slice<A: Atomic>(slice: &[u8]) -> Result<A, A::ParseError> { | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /// 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>; |     fn f() -> AtomicFactory<Self>; | ||||||
|  |     /// Static equivalent of [`ExtFactory::parse_slice`].
 | ||||||
|     fn parse_slice(slice: &[u8]) -> Result<Self, Self::ParseError>; |     fn parse_slice(slice: &[u8]) -> Result<Self, Self::ParseError>; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,12 +1,18 @@ | |||||||
|  | //! [`Plain`] type for storing raw byte sequnces.
 | ||||||
|  | 
 | ||||||
| use std::fmt::Display; | use std::fmt::Display; | ||||||
| 
 | 
 | ||||||
| use crate::std::atomic::*; | use crate::std::atomic::*; | ||||||
| 
 | 
 | ||||||
| #[derive(Clone)] | /// Raw bytes storage. Use [`Plain::raw`] to get the data.
 | ||||||
|  | ///
 | ||||||
|  | /// Note: this type uses [`Deserializer::read_all`] for parsing.
 | ||||||
|  | #[derive(Clone, Debug)] | ||||||
| pub struct Plain { | pub struct Plain { | ||||||
|     data: Vec<u8>, |     data: Vec<u8>, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /// This shouldn't happen given [`Deserializer::read_all`] being used for parsing.
 | ||||||
| #[derive(Debug)] | #[derive(Debug)] | ||||||
| pub enum PlainParseError {} | pub enum PlainParseError {} | ||||||
| 
 | 
 | ||||||
| @ -40,9 +46,15 @@ impl Atomic for Plain { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl Plain { | impl Plain { | ||||||
|  |     /// Copy bytes into a new instance.
 | ||||||
|     pub fn from_slice(slice: &[u8]) -> Self { |     pub fn from_slice(slice: &[u8]) -> Self { | ||||||
|         Plain { data: slice.into() } |         Plain { data: slice.into() } | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     /// Copy of bytes stored inside.
 | ||||||
|  |     pub fn raw(&self) -> Vec<u8> { | ||||||
|  |         self.data.clone() | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[cfg(test)] | #[cfg(test)] | ||||||
|  | |||||||
| @ -1,3 +1,8 @@ | |||||||
|  | //! Utilities to convert from typeless instances defined in [`crate::core`].
 | ||||||
|  | //! See [`TypelessMentionable::cast`]/[`Point::cast`].
 | ||||||
|  | //!
 | ||||||
|  | //! p.s. the implementation is horrific.
 | ||||||
|  | 
 | ||||||
| use crate::core::*; | use crate::core::*; | ||||||
| use crate::std::*; | use crate::std::*; | ||||||
| 
 | 
 | ||||||
| @ -5,13 +10,22 @@ struct CastResolver<'a, Ctx: 'a + Context> { | |||||||
|     points: Vec<Point<'a, Ctx, TypelessMentionable<'a, Ctx>>>, |     points: Vec<Point<'a, Ctx, TypelessMentionable<'a, Ctx>>>, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /// Used to represent errors that might arise during resolution/parsion.
 | ||||||
|  | /// Is expected to be classified as [`Context::LookupError`] rather than [`Factory::ParseError`].
 | ||||||
|  | /// [`CastError::AddressIndexOutOfBounds`] and [`CastError::AddressPointMismatch`]
 | ||||||
|  | /// variants generally shouldn't happen.
 | ||||||
| #[derive(Debug)] | #[derive(Debug)] | ||||||
| pub enum CastError<'a> { | pub enum CastError<'a> { | ||||||
|     Typeless(TypelessError<'a>), |     Typeless(TypelessError<'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`] and/or [`Mentionable::topology`].
 | ||||||
|     AddressIndexOutOfBounds { |     AddressIndexOutOfBounds { | ||||||
|         index: usize, |         index: usize, | ||||||
|         length: usize, |         length: usize, | ||||||
|     }, |     }, | ||||||
|  |     /// See [`CastError::AddressIndexOutOfBounds`].
 | ||||||
|     AddressPointMismatch { |     AddressPointMismatch { | ||||||
|         expected: Hash, |         expected: Hash, | ||||||
|         received: Hash, |         received: Hash, | ||||||
| @ -84,12 +98,15 @@ where | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /// Returned by [`TypelessMentionable::cast`].
 | ||||||
| pub type CastResult<'a, Ctx, A> = | pub type CastResult<'a, Ctx, A> = | ||||||
|     Result<A, <<A as Mentionable<'a, Ctx>>::Fctr as Factory<'a, Ctx>>::ParseError>; |     Result<A, <<A as Mentionable<'a, Ctx>>::Fctr as Factory<'a, Ctx>>::ParseError>; | ||||||
|  | 
 | ||||||
| impl<'a, Ctx: Context> TypelessMentionable<'a, Ctx> | impl<'a, Ctx: Context> TypelessMentionable<'a, Ctx> | ||||||
| where | where | ||||||
|     Ctx::LookupError<'a>: From<CastError<'a>>, |     Ctx::LookupError<'a>: From<CastError<'a>>, | ||||||
| { | { | ||||||
|  |     /// Re-parse the object as if it is of a specific type. Has potential to break topology.
 | ||||||
|     pub fn cast<A: Mentionable<'a, Ctx>>(&self, factory: A::Fctr) -> CastResult<'a, Ctx, A> { |     pub fn cast<A: Mentionable<'a, Ctx>>(&self, factory: A::Fctr) -> CastResult<'a, Ctx, A> { | ||||||
|         factory.parse_slice( |         factory.parse_slice( | ||||||
|             &self.bytes(), |             &self.bytes(), | ||||||
| @ -99,3 +116,35 @@ where | |||||||
|         ) |         ) | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | impl<'a, Ctx: Context> Point<'a, Ctx, TypelessMentionable<'a, Ctx>> | ||||||
|  | where | ||||||
|  |     Ctx::LookupError<'a>: From<CastError<'a>>, | ||||||
|  | { | ||||||
|  |     /// See [`TypelessMentionable::cast`]
 | ||||||
|  |     pub fn cast<A: Mentionable<'a, Ctx>>(&self, factory: A::Fctr) -> Point<'a, Ctx, A> { | ||||||
|  |         let typeless_origin = self.origin.clone(); | ||||||
|  |         let origin: Rc<dyn Origin<Ctx, Mtbl = A>> = 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, | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | |||||||
| @ -71,7 +71,7 @@ impl<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> Factory<'a, Ctx> | |||||||
|         Ok(if address.point == HASH_ZEROS { |         Ok(if address.point == HASH_ZEROS { | ||||||
|             Nullable::Null(factory) |             Nullable::Null(factory) | ||||||
|         } else { |         } else { | ||||||
|             Nullable::NotNull(Point::from_point(address, factory, resolver)) |             Nullable::NotNull(Point::from_address(address, factory, resolver)) | ||||||
|         }) |         }) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user