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>>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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> {
 | 
			
		||||
    fn map<B: Mentionable<'a, Ctx>>(
 | 
			
		||||
        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> {
 | 
			
		||||
    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: address.point,
 | 
			
		||||
            origin: Rc::new(ResolverOrigin {
 | 
			
		||||
@ -191,7 +205,7 @@ impl Addresses {
 | 
			
		||||
        resolver: Rc<dyn Resolver<'a, Ctx>>,
 | 
			
		||||
        factory: A::Fctr,
 | 
			
		||||
    ) -> Result<Point<'a, Ctx, A>, &'b [u8]> {
 | 
			
		||||
        Ok(Point::from_point(
 | 
			
		||||
        Ok(Point::from_address(
 | 
			
		||||
            self.next(deserializer)?,
 | 
			
		||||
            factory,
 | 
			
		||||
            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 {
 | 
			
		||||
    /// Short-hand for getting specific [`AtomicFactory`].
 | 
			
		||||
    fn f() -> AtomicFactory<Self>;
 | 
			
		||||
    /// Static equivalent of [`ExtFactory::parse_slice`].
 | 
			
		||||
    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 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 {
 | 
			
		||||
    data: Vec<u8>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// This shouldn't happen given [`Deserializer::read_all`] being used for parsing.
 | 
			
		||||
#[derive(Debug)]
 | 
			
		||||
pub enum PlainParseError {}
 | 
			
		||||
 | 
			
		||||
@ -40,9 +46,15 @@ impl Atomic for Plain {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Plain {
 | 
			
		||||
    /// Copy bytes into a new instance.
 | 
			
		||||
    pub fn from_slice(slice: &[u8]) -> Self {
 | 
			
		||||
        Plain { data: slice.into() }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Copy of bytes stored inside.
 | 
			
		||||
    pub fn raw(&self) -> Vec<u8> {
 | 
			
		||||
        self.data.clone()
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[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::std::*;
 | 
			
		||||
 | 
			
		||||
@ -5,13 +10,22 @@ struct CastResolver<'a, Ctx: 'a + Context> {
 | 
			
		||||
    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)]
 | 
			
		||||
pub enum CastError<'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 {
 | 
			
		||||
        index: usize,
 | 
			
		||||
        length: usize,
 | 
			
		||||
    },
 | 
			
		||||
    /// See [`CastError::AddressIndexOutOfBounds`].
 | 
			
		||||
    AddressPointMismatch {
 | 
			
		||||
        expected: Hash,
 | 
			
		||||
        received: Hash,
 | 
			
		||||
@ -84,12 +98,15 @@ where
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Returned by [`TypelessMentionable::cast`].
 | 
			
		||||
pub type CastResult<'a, Ctx, A> =
 | 
			
		||||
    Result<A, <<A as Mentionable<'a, Ctx>>::Fctr as Factory<'a, Ctx>>::ParseError>;
 | 
			
		||||
 | 
			
		||||
impl<'a, Ctx: Context> TypelessMentionable<'a, Ctx>
 | 
			
		||||
where
 | 
			
		||||
    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> {
 | 
			
		||||
        factory.parse_slice(
 | 
			
		||||
            &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 {
 | 
			
		||||
            Nullable::Null(factory)
 | 
			
		||||
        } 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