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