cast
This commit is contained in:
parent
379e8bc2cd
commit
d5bcd53335
113
src/core.rs
113
src/core.rs
@ -5,11 +5,32 @@ use crate::func::*;
|
|||||||
pub trait Context {
|
pub trait Context {
|
||||||
type T: Monad;
|
type T: Monad;
|
||||||
|
|
||||||
|
type LookupError: Error;
|
||||||
|
|
||||||
fn hash(s: &[u8]) -> Hash;
|
fn hash(s: &[u8]) -> Hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub enum ResolutionError<L, P> {
|
||||||
|
Lookup(L),
|
||||||
|
Parse(P),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type ResolutionResult<'a, Ctx, A> = Result<
|
||||||
|
Rc<A>,
|
||||||
|
ResolutionError<
|
||||||
|
<Ctx as Context>::LookupError,
|
||||||
|
<<A as Mentionable<'a, Ctx>>::Fctr as Factory<'a, Ctx>>::ParseError,
|
||||||
|
>,
|
||||||
|
>;
|
||||||
|
|
||||||
|
pub type Wrapped<'a, Ctx, A> = <<Ctx as Context>::T as WeakFunctor>::F<'a, A>;
|
||||||
|
|
||||||
|
pub type Resolution<'a, Ctx, A> = Wrapped<'a, Ctx, ResolutionResult<'a, Ctx, A>>;
|
||||||
|
|
||||||
pub const HASH_SIZE: usize = 32;
|
pub const HASH_SIZE: usize = 32;
|
||||||
|
|
||||||
|
pub const HASH_ZEROS: [u8; HASH_SIZE] = [0; HASH_SIZE];
|
||||||
|
|
||||||
pub type Hash = [u8; HASH_SIZE];
|
pub type Hash = [u8; HASH_SIZE];
|
||||||
|
|
||||||
pub trait Serializer {
|
pub trait Serializer {
|
||||||
@ -45,39 +66,45 @@ pub trait Mentionable<'a, Ctx: 'a + Context>: 'a + Serializable {
|
|||||||
fn points(&self) -> Vec<Point<'a, Ctx, TypelessMentionable<'a, Ctx>>>;
|
fn points(&self) -> Vec<Point<'a, Ctx, TypelessMentionable<'a, Ctx>>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub type HashResolution<'a, Ctx> =
|
||||||
|
Wrapped<'a, Ctx, Result<(Vec<u8>, Rc<dyn Resolver<'a, Ctx>>), <Ctx as Context>::LookupError>>;
|
||||||
|
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
pub struct Address {
|
||||||
|
pub point: Hash,
|
||||||
|
pub index: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait Resolver<'a, Ctx: 'a + Context>: 'a {
|
||||||
|
fn resolve(self: Rc<Self>, address: Address) -> HashResolution<'a, Ctx>;
|
||||||
|
}
|
||||||
|
|
||||||
pub trait Deserializer {
|
pub trait Deserializer {
|
||||||
fn read_n(&mut self, n: usize) -> &[u8];
|
fn read_n(&mut self, n: usize) -> &[u8];
|
||||||
fn read_all(&mut self, n: usize) -> &[u8];
|
fn read_all(&mut self) -> &[u8];
|
||||||
|
fn tell(&self) -> usize;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait ExtDeserialiser {
|
pub type ParseResult<'a, Ctx, F> =
|
||||||
fn read_n_const<const N: usize>(&mut self) -> Result<[u8; N], &[u8]>;
|
Result<<F as Factory<'a, Ctx>>::Mtbl, <F as Factory<'a, Ctx>>::ParseError>;
|
||||||
}
|
|
||||||
|
|
||||||
impl<D: ?Sized + Deserializer> ExtDeserialiser for D {
|
|
||||||
fn read_n_const<const N: usize>(&mut self) -> Result<[u8; N], &[u8]> {
|
|
||||||
let slice = self.read_n(N);
|
|
||||||
match slice.try_into() {
|
|
||||||
Ok(array) => Ok(array),
|
|
||||||
Err(_) => Err(slice),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait Factory<'a, Ctx: 'a + Context>: Clone + 'a {
|
pub trait Factory<'a, Ctx: 'a + Context>: Clone + 'a {
|
||||||
type Mtbl: Mentionable<'a, Ctx, Fctr = Self>;
|
type Mtbl: Mentionable<'a, Ctx, Fctr = Self>;
|
||||||
type ParseError: Error;
|
type ParseError: 'a + Error;
|
||||||
|
|
||||||
fn deserialize(
|
fn deserialize(
|
||||||
&self,
|
&self,
|
||||||
deserializer: &mut dyn Deserializer,
|
deserializer: &mut dyn Deserializer,
|
||||||
) -> Result<Self::Mtbl, Self::ParseError>;
|
resolver: Rc<dyn Resolver<'a, Ctx>>,
|
||||||
|
) -> ParseResult<'a, Ctx, Self>;
|
||||||
|
|
||||||
|
fn unexpected_tail(&self, tail: &[u8]) -> Self::ParseError;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Origin<'a, Ctx: 'a + Context>: 'a {
|
pub trait Origin<'a, Ctx: 'a + Context>: 'a {
|
||||||
type Mtbl: Mentionable<'a, Ctx>;
|
type Mtbl: Mentionable<'a, Ctx>;
|
||||||
fn factory(&self) -> <Self::Mtbl as Mentionable<'a, Ctx>>::Fctr;
|
fn factory(&self) -> <Self::Mtbl as Mentionable<'a, Ctx>>::Fctr;
|
||||||
fn resolve(&self) -> <<Ctx as Context>::T as WeakFunctor>::F<'a, Rc<Self::Mtbl>>;
|
fn resolve(self: Rc<Self>) -> Resolution<'a, Ctx, Self::Mtbl>;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct LocalOrigin<A>(Rc<A>);
|
struct LocalOrigin<A>(Rc<A>);
|
||||||
@ -89,8 +116,8 @@ impl<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> Origin<'a, Ctx> for LocalOr
|
|||||||
self.0.factory()
|
self.0.factory()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve(&self) -> <<Ctx as Context>::T as WeakFunctor>::F<'a, Rc<Self::Mtbl>> {
|
fn resolve(self: Rc<Self>) -> Resolution<'a, Ctx, Self::Mtbl> {
|
||||||
<Ctx::T as Applicative>::pure(self.0.clone())
|
<Ctx::T as Applicative>::pure(Ok(self.0.clone()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -129,8 +156,8 @@ impl<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> Point<'a, Ctx, A> {
|
|||||||
Self::from_fields(point, Rc::new(origin))
|
Self::from_fields(point, Rc::new(origin))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn resolve(&self) -> <<Ctx as Context>::T as WeakFunctor>::F<'a, Rc<A>> {
|
pub fn resolve(&self) -> Resolution<'a, Ctx, A> {
|
||||||
self.origin.resolve()
|
self.origin.clone().resolve()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -154,10 +181,14 @@ pub struct TypelessMentionable<'a, Ctx: 'a + Context> {
|
|||||||
|
|
||||||
type TypelessParsed<'a, Ctx> = Result<TypelessMentionable<'a, Ctx>, Box<dyn 'a + Error>>;
|
type TypelessParsed<'a, Ctx> = Result<TypelessMentionable<'a, Ctx>, Box<dyn 'a + Error>>;
|
||||||
|
|
||||||
type TypelessDeserialize<'a, Ctx> = dyn 'a + Fn(&mut dyn Deserializer) -> TypelessParsed<'a, Ctx>;
|
type TypelessDeserialize<'a, Ctx> =
|
||||||
|
dyn 'a + Fn(&mut dyn Deserializer, Rc<dyn Resolver<'a, Ctx>>) -> TypelessParsed<'a, Ctx>;
|
||||||
|
|
||||||
|
type TypelessUnexpectedTail<'a> = dyn 'a + Fn(&[u8]) -> TypelessError<'a>;
|
||||||
|
|
||||||
pub struct TypelessFactory<'a, Ctx: 'a + Context> {
|
pub struct TypelessFactory<'a, Ctx: 'a + Context> {
|
||||||
t_deserialize: Rc<TypelessDeserialize<'a, Ctx>>,
|
t_deserialize: Rc<TypelessDeserialize<'a, Ctx>>,
|
||||||
|
t_unexpected_tail: Rc<TypelessUnexpectedTail<'a>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, Ctx: 'a + Context> Serializable for TypelessMentionable<'a, Ctx> {
|
impl<'a, Ctx: 'a + Context> Serializable for TypelessMentionable<'a, Ctx> {
|
||||||
@ -186,6 +217,7 @@ impl<'a, Ctx: 'a + Context> Clone for TypelessFactory<'a, Ctx> {
|
|||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
Self {
|
Self {
|
||||||
t_deserialize: self.t_deserialize.clone(),
|
t_deserialize: self.t_deserialize.clone(),
|
||||||
|
t_unexpected_tail: self.t_unexpected_tail.clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -209,17 +241,22 @@ impl<'a, Ctx: 'a + Context> Factory<'a, Ctx> for TypelessFactory<'a, Ctx> {
|
|||||||
fn deserialize(
|
fn deserialize(
|
||||||
&self,
|
&self,
|
||||||
deserializer: &mut dyn Deserializer,
|
deserializer: &mut dyn Deserializer,
|
||||||
) -> Result<Self::Mtbl, Self::ParseError> {
|
resolver: Rc<dyn Resolver<'a, Ctx>>,
|
||||||
match (self.t_deserialize)(deserializer) {
|
) -> ParseResult<'a, Ctx, Self> {
|
||||||
|
match (self.t_deserialize)(deserializer, resolver) {
|
||||||
Ok(mentionable) => Ok(mentionable),
|
Ok(mentionable) => Ok(mentionable),
|
||||||
Err(error) => Err(TypelessError(error)),
|
Err(error) => Err(TypelessError(error)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn unexpected_tail(&self, tail: &[u8]) -> Self::ParseError {
|
||||||
|
(self.t_unexpected_tail)(tail)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, Ctx: 'a + Context> TypelessMentionable<'a, Ctx> {
|
impl<'a, Ctx: 'a + Context> TypelessMentionable<'a, Ctx> {
|
||||||
pub fn from_mentionable<A: Mentionable<'a, Ctx>>(mentionable: Rc<A>) -> Self {
|
pub fn from_typed<A: Mentionable<'a, Ctx>>(mentionable: Rc<A>) -> Self {
|
||||||
let factory = TypelessFactory::from_factory(mentionable.factory());
|
let factory = TypelessFactory::from_typed(mentionable.factory());
|
||||||
let topology = mentionable.topology();
|
let topology = mentionable.topology();
|
||||||
let points = mentionable.points();
|
let points = mentionable.points();
|
||||||
TypelessMentionable {
|
TypelessMentionable {
|
||||||
@ -232,16 +269,24 @@ impl<'a, Ctx: 'a + Context> TypelessMentionable<'a, Ctx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, Ctx: 'a + Context> TypelessFactory<'a, Ctx> {
|
impl<'a, Ctx: 'a + Context> TypelessFactory<'a, Ctx> {
|
||||||
pub fn from_factory<F: Factory<'a, Ctx>>(factory: F) -> Self {
|
pub fn from_typed<F: Factory<'a, Ctx>>(factory: F) -> Self {
|
||||||
|
let tail_factory = factory.clone();
|
||||||
TypelessFactory {
|
TypelessFactory {
|
||||||
t_deserialize: Rc::new(
|
t_deserialize: Rc::new(move |deserializer, resolver| {
|
||||||
move |deserializer| match factory.deserialize(deserializer) {
|
match factory.deserialize(deserializer, resolver) {
|
||||||
Ok(mentionable) => {
|
Ok(mentionable) => Ok(TypelessMentionable::from_typed(Rc::new(mentionable))),
|
||||||
Ok(TypelessMentionable::from_mentionable(Rc::new(mentionable)))
|
|
||||||
}
|
|
||||||
Err(error) => Err(Box::new(error)),
|
Err(error) => Err(Box::new(error)),
|
||||||
},
|
}
|
||||||
),
|
}),
|
||||||
|
t_unexpected_tail: Rc::new(move |tail| {
|
||||||
|
TypelessError::from_typed(tail_factory.unexpected_tail(tail))
|
||||||
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a> TypelessError<'a> {
|
||||||
|
pub fn from_typed<E: 'a + Error>(error: E) -> Self {
|
||||||
|
TypelessError(Box::new(error))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
236
src/std.rs
236
src/std.rs
@ -1,6 +1,9 @@
|
|||||||
pub mod atomic;
|
pub mod atomic;
|
||||||
|
pub mod cast;
|
||||||
pub mod inlining;
|
pub mod inlining;
|
||||||
|
pub mod nullable;
|
||||||
|
|
||||||
|
use std::cmp::min;
|
||||||
use std::{error::Error, fmt::Display, rc::Rc};
|
use std::{error::Error, fmt::Display, rc::Rc};
|
||||||
|
|
||||||
use crate::core::*;
|
use crate::core::*;
|
||||||
@ -8,23 +11,38 @@ use crate::func::*;
|
|||||||
|
|
||||||
struct WrappedOrigin<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> {
|
struct WrappedOrigin<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> {
|
||||||
w_factory: A::Fctr,
|
w_factory: A::Fctr,
|
||||||
w_resolve: Box<dyn 'a + Fn() -> <<Ctx as Context>::T as WeakFunctor>::F<'a, Rc<A>>>,
|
w_resolve: Box<dyn 'a + Fn() -> Resolution<'a, Ctx, A>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
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>,
|
||||||
map_mentionable: impl 'a + Clone + Fn(Rc<Self::Mtbl>) -> B,
|
map_ok: impl 'a + Clone + Fn(Rc<Self::Mtbl>) -> B,
|
||||||
|
map_err: impl 'a
|
||||||
|
+ Clone
|
||||||
|
+ Fn(
|
||||||
|
<<Self::Mtbl as Mentionable<'a, Ctx>>::Fctr as Factory<'a, Ctx>>::ParseError,
|
||||||
|
) -> <B::Fctr as Factory<'a, Ctx>>::ParseError,
|
||||||
map_factory: impl 'a + FnOnce(<Self::Mtbl as Mentionable<'a, Ctx>>::Fctr) -> B::Fctr,
|
map_factory: impl 'a + FnOnce(<Self::Mtbl as Mentionable<'a, Ctx>>::Fctr) -> B::Fctr,
|
||||||
) -> WrappedOrigin<'a, Ctx, B>;
|
) -> WrappedOrigin<'a, Ctx, B>;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn map_resolve<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>, B: Mentionable<'a, Ctx>>(
|
fn map_resolve<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>, B: Mentionable<'a, Ctx>>(
|
||||||
resolve: impl 'a + Fn() -> <<Ctx as Context>::T as WeakFunctor>::F<'a, Rc<A>>,
|
resolve: impl 'a + Fn() -> Resolution<'a, Ctx, A>,
|
||||||
map_mentionable: impl 'a + Fn(Rc<A>) -> B,
|
map_ok: impl 'a + Fn(Rc<A>) -> B,
|
||||||
) -> <<Ctx as Context>::T as WeakFunctor>::F<'a, Rc<B>> {
|
map_err: impl 'a
|
||||||
|
+ Fn(<A::Fctr as Factory<'a, Ctx>>::ParseError) -> <B::Fctr as Factory<'a, Ctx>>::ParseError,
|
||||||
|
) -> Resolution<'a, Ctx, B> {
|
||||||
Ctx::T::fmap(
|
Ctx::T::fmap(
|
||||||
move |resolved| Rc::new(map_mentionable(resolved)),
|
move |resolved| match resolved {
|
||||||
|
Ok(mentionable) => Ok(Rc::new(map_ok(mentionable))),
|
||||||
|
Err(ResolutionError::Parse(parse_error)) => {
|
||||||
|
Err(ResolutionError::Parse(map_err(parse_error)))
|
||||||
|
}
|
||||||
|
Err(ResolutionError::Lookup(lookup_error)) => {
|
||||||
|
Err(ResolutionError::Lookup(lookup_error))
|
||||||
|
}
|
||||||
|
},
|
||||||
resolve(),
|
resolve(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -32,7 +50,12 @@ fn map_resolve<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>, B: Mentionable<'a
|
|||||||
impl<'a, Ctx: 'a + Context, O: ?Sized + Origin<'a, Ctx>> MappableOrigin<'a, Ctx> for O {
|
impl<'a, Ctx: 'a + Context, O: ?Sized + Origin<'a, Ctx>> MappableOrigin<'a, Ctx> for O {
|
||||||
fn map<B: Mentionable<'a, Ctx>>(
|
fn map<B: Mentionable<'a, Ctx>>(
|
||||||
self: Rc<Self>,
|
self: Rc<Self>,
|
||||||
map_mentionable: impl 'a + Clone + Fn(Rc<Self::Mtbl>) -> B,
|
map_ok: impl 'a + Clone + Fn(Rc<Self::Mtbl>) -> B,
|
||||||
|
map_err: impl 'a
|
||||||
|
+ Clone
|
||||||
|
+ Fn(
|
||||||
|
<<Self::Mtbl as Mentionable<'a, Ctx>>::Fctr as Factory<'a, Ctx>>::ParseError,
|
||||||
|
) -> <B::Fctr as Factory<'a, Ctx>>::ParseError,
|
||||||
map_factory: impl 'a + FnOnce(<Self::Mtbl as Mentionable<'a, Ctx>>::Fctr) -> B::Fctr,
|
map_factory: impl 'a + FnOnce(<Self::Mtbl as Mentionable<'a, Ctx>>::Fctr) -> B::Fctr,
|
||||||
) -> WrappedOrigin<'a, Ctx, B> {
|
) -> WrappedOrigin<'a, Ctx, B> {
|
||||||
let origin = self.clone();
|
let origin = self.clone();
|
||||||
@ -40,11 +63,9 @@ impl<'a, Ctx: 'a + Context, O: ?Sized + Origin<'a, Ctx>> MappableOrigin<'a, Ctx>
|
|||||||
w_factory: map_factory(self.factory()),
|
w_factory: map_factory(self.factory()),
|
||||||
w_resolve: Box::new(move || {
|
w_resolve: Box::new(move || {
|
||||||
let origin = origin.clone();
|
let origin = origin.clone();
|
||||||
let map_mentionable = map_mentionable.clone();
|
let map_ok = map_ok.clone();
|
||||||
map_resolve(
|
let map_err = map_err.clone();
|
||||||
move || origin.resolve(),
|
map_resolve(move || origin.clone().resolve(), map_ok, map_err)
|
||||||
map_mentionable,
|
|
||||||
)
|
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -57,7 +78,7 @@ impl<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> Origin<'a, Ctx> for Wrapped
|
|||||||
self.w_factory.clone()
|
self.w_factory.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve(&self) -> <<Ctx as Context>::T as WeakFunctor>::F<'a, Rc<Self::Mtbl>> {
|
fn resolve(self: Rc<Self>) -> Resolution<'a, Ctx, A> {
|
||||||
(self.w_resolve)()
|
(self.w_resolve)()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -67,8 +88,9 @@ impl<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> Point<'a, Ctx, A> {
|
|||||||
Point {
|
Point {
|
||||||
point: self.point,
|
point: self.point,
|
||||||
origin: Rc::new(self.origin.clone().map(
|
origin: Rc::new(self.origin.clone().map(
|
||||||
TypelessMentionable::from_mentionable,
|
TypelessMentionable::from_typed,
|
||||||
TypelessFactory::from_factory,
|
TypelessError::from_typed,
|
||||||
|
TypelessFactory::from_typed,
|
||||||
)),
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -121,6 +143,64 @@ impl Display for PointParseError {
|
|||||||
|
|
||||||
impl Error for PointParseError {}
|
impl Error for PointParseError {}
|
||||||
|
|
||||||
|
impl From<&[u8]> for PointParseError {
|
||||||
|
fn from(value: &[u8]) -> Self {
|
||||||
|
PointParseError::WrongLength(value.len())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 {
|
||||||
|
Point {
|
||||||
|
point: address.point,
|
||||||
|
origin: Rc::new(ResolverOrigin {
|
||||||
|
r_factory: factory,
|
||||||
|
r_address: address,
|
||||||
|
r_resolver: resolver,
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> AsRef<[u8]> for Point<'a, Ctx, A> {
|
||||||
|
fn as_ref(&self) -> &[u8] {
|
||||||
|
&self.point
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Addresses {
|
||||||
|
current: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Addresses {
|
||||||
|
fn next<'a>(&mut self, deserializer: &'a mut dyn Deserializer) -> Result<Address, &'a [u8]> {
|
||||||
|
let point = deserializer.read_n_const::<HASH_SIZE>()?;
|
||||||
|
let address = Address {
|
||||||
|
point,
|
||||||
|
index: self.current,
|
||||||
|
};
|
||||||
|
self.current += 1;
|
||||||
|
Ok(address)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn next_point<'a, 'b, Ctx: 'a + Context, A: Mentionable<'a, Ctx>>(
|
||||||
|
&mut self,
|
||||||
|
deserializer: &'b mut dyn Deserializer,
|
||||||
|
resolver: Rc<dyn Resolver<'a, Ctx>>,
|
||||||
|
factory: A::Fctr,
|
||||||
|
) -> Result<Point<'a, Ctx, A>, &'b [u8]> {
|
||||||
|
Ok(Point::from_point(
|
||||||
|
self.next(deserializer)?,
|
||||||
|
factory,
|
||||||
|
resolver,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn start() -> Self {
|
||||||
|
Addresses { current: 0 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a, Ctx: 'a + Context, F: Factory<'a, Ctx>> Factory<'a, Ctx> for PointFactory<F> {
|
impl<'a, Ctx: 'a + Context, F: Factory<'a, Ctx>> Factory<'a, Ctx> for PointFactory<F> {
|
||||||
type Mtbl = Point<'a, Ctx, F::Mtbl>;
|
type Mtbl = Point<'a, Ctx, F::Mtbl>;
|
||||||
|
|
||||||
@ -129,10 +209,128 @@ impl<'a, Ctx: 'a + Context, F: Factory<'a, Ctx>> Factory<'a, Ctx> for PointFacto
|
|||||||
fn deserialize(
|
fn deserialize(
|
||||||
&self,
|
&self,
|
||||||
deserializer: &mut dyn Deserializer,
|
deserializer: &mut dyn Deserializer,
|
||||||
) -> Result<Self::Mtbl, Self::ParseError> {
|
resolver: Rc<dyn Resolver<'a, Ctx>>,
|
||||||
match deserializer.read_n_const::<HASH_SIZE>() {
|
) -> ParseResult<'a, Ctx, Self> {
|
||||||
Ok(point) => Ok(Point {point, origin: todo!()}),
|
let mut addresses = Addresses::start();
|
||||||
Err(slice) => Err(PointParseError::WrongLength(slice.len())),
|
Ok(addresses.next_point(deserializer, resolver, self.factory.clone())?)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn unexpected_tail(&self, tail: &[u8]) -> Self::ParseError {
|
||||||
|
PointParseError::WrongLength(HASH_SIZE + tail.len())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ResolverOrigin<'a, Ctx: 'a + Context, F: Factory<'a, Ctx>> {
|
||||||
|
r_factory: F,
|
||||||
|
r_address: Address,
|
||||||
|
r_resolver: Rc<dyn Resolver<'a, Ctx>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn _resolve_origin<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>>(
|
||||||
|
origin: Rc<ResolverOrigin<'a, Ctx, A::Fctr>>,
|
||||||
|
) -> Resolution<'a, Ctx, A> {
|
||||||
|
let resolution = origin.r_resolver.clone().resolve(origin.r_address);
|
||||||
|
Ctx::T::fmap(
|
||||||
|
move |resolved| match resolved {
|
||||||
|
Ok((src, resolver)) => match origin.r_factory.parse_slice(&src, resolver) {
|
||||||
|
Ok(mentionable) => Ok(Rc::new(mentionable)),
|
||||||
|
Err(parse_error) => Err(ResolutionError::Parse(parse_error)),
|
||||||
|
},
|
||||||
|
Err(lookup_error) => Err(ResolutionError::Lookup(lookup_error)),
|
||||||
|
},
|
||||||
|
resolution,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, Ctx: 'a + Context, F: Factory<'a, Ctx>> Origin<'a, Ctx> for ResolverOrigin<'a, Ctx, F> {
|
||||||
|
type Mtbl = F::Mtbl;
|
||||||
|
|
||||||
|
fn factory(&self) -> <Self::Mtbl as Mentionable<'a, Ctx>>::Fctr {
|
||||||
|
self.r_factory.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn resolve(self: Rc<Self>) -> Resolution<'a, Ctx, Self::Mtbl> {
|
||||||
|
_resolve_origin(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct SliceDeserializer<'a> {
|
||||||
|
slice: &'a [u8],
|
||||||
|
pos: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> From<&'a [u8]> for SliceDeserializer<'a> {
|
||||||
|
fn from(value: &'a [u8]) -> Self {
|
||||||
|
SliceDeserializer {
|
||||||
|
slice: value,
|
||||||
|
pos: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Deserializer for SliceDeserializer<'a> {
|
||||||
|
fn read_n(&mut self, n: usize) -> &[u8] {
|
||||||
|
let (left, right) = self.slice.split_at(min(n, self.slice.len()));
|
||||||
|
self.slice = right;
|
||||||
|
self.pos += left.len();
|
||||||
|
left
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_all(&mut self) -> &[u8] {
|
||||||
|
let left = self.slice;
|
||||||
|
self.slice = &[];
|
||||||
|
self.pos += left.len();
|
||||||
|
left
|
||||||
|
}
|
||||||
|
|
||||||
|
fn tell(&self) -> usize {
|
||||||
|
self.pos
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn _parse_slice<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>>(
|
||||||
|
factory: &A::Fctr,
|
||||||
|
slice: &[u8],
|
||||||
|
resolver: Rc<dyn Resolver<'a, Ctx>>,
|
||||||
|
) -> ParseResult<'a, Ctx, A::Fctr> {
|
||||||
|
let mut deserializer = SliceDeserializer::from(slice);
|
||||||
|
let mentionable = factory.deserialize(&mut deserializer, resolver)?;
|
||||||
|
let tail = deserializer.read_all();
|
||||||
|
if tail.is_empty() {
|
||||||
|
Ok(mentionable)
|
||||||
|
} else {
|
||||||
|
Err(factory.unexpected_tail(tail))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait ExtFactory<'a, Ctx: 'a + Context>: Factory<'a, Ctx> {
|
||||||
|
fn parse_slice(
|
||||||
|
&self,
|
||||||
|
slice: &[u8],
|
||||||
|
resolver: Rc<dyn Resolver<'a, Ctx>>,
|
||||||
|
) -> ParseResult<'a, Ctx, Self>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, Ctx: 'a + Context, F: Factory<'a, Ctx>> ExtFactory<'a, Ctx> for F {
|
||||||
|
fn parse_slice(
|
||||||
|
&self,
|
||||||
|
slice: &[u8],
|
||||||
|
resolver: Rc<dyn Resolver<'a, Ctx>>,
|
||||||
|
) -> ParseResult<'a, Ctx, Self> {
|
||||||
|
_parse_slice::<Ctx, F::Mtbl>(self, slice, resolver)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait ExtDeserializer {
|
||||||
|
fn read_n_const<const N: usize>(&mut self) -> Result<[u8; N], &[u8]>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<D: ?Sized + Deserializer> ExtDeserializer for D {
|
||||||
|
fn read_n_const<const N: usize>(&mut self) -> Result<[u8; N], &[u8]> {
|
||||||
|
let slice = self.read_n(N);
|
||||||
|
match slice.try_into() {
|
||||||
|
Ok(array) => Ok(array),
|
||||||
|
Err(_) => Err(slice),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
use std::{error::Error, marker::PhantomData};
|
use std::{error::Error, marker::PhantomData, rc::Rc};
|
||||||
|
|
||||||
use crate::core::*;
|
use crate::core::*;
|
||||||
|
|
||||||
pub trait Atomic: 'static + Sized + Clone + Serializable {
|
pub trait Atomic: 'static + Sized + Clone + Serializable {
|
||||||
type ParseError: Error;
|
type ParseError: Error;
|
||||||
fn deserialize(deserializer: &mut dyn Deserializer) -> Result<Self, Self::ParseError>;
|
fn deserialize(deserializer: &mut dyn Deserializer) -> Result<Self, Self::ParseError>;
|
||||||
|
fn unexpected_tail(tail: &[u8]) -> Self::ParseError;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct AtomicFactory<A: Atomic>(PhantomData<A>);
|
pub struct AtomicFactory<A: Atomic>(PhantomData<A>);
|
||||||
@ -45,7 +46,12 @@ impl<'a, Ctx: 'a + Context, A: Atomic> Factory<'a, Ctx> for AtomicFactory<A> {
|
|||||||
fn deserialize(
|
fn deserialize(
|
||||||
&self,
|
&self,
|
||||||
deserializer: &mut dyn Deserializer,
|
deserializer: &mut dyn Deserializer,
|
||||||
) -> Result<Self::Mtbl, Self::ParseError> {
|
_resolver: Rc<dyn Resolver<'a, Ctx>>,
|
||||||
|
) -> ParseResult<'a, Ctx, Self> {
|
||||||
A::deserialize(deserializer)
|
A::deserialize(deserializer)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn unexpected_tail(&self, tail: &[u8]) -> Self::ParseError {
|
||||||
|
A::unexpected_tail(tail)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
61
src/std/cast.rs
Normal file
61
src/std/cast.rs
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
use crate::core::*;
|
||||||
|
use crate::std::*;
|
||||||
|
|
||||||
|
struct CastResolver<'a, Ctx: 'a + Context> {
|
||||||
|
points: Vec<Point<'a, Ctx, TypelessMentionable<'a, Ctx>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, Ctx: 'a + Context> Resolver<'a, Ctx> for CastResolver<'a, Ctx>
|
||||||
|
where
|
||||||
|
Ctx::LookupError: From<TypelessError<'a>>,
|
||||||
|
{
|
||||||
|
fn resolve(self: Rc<Self>, address: Address) -> HashResolution<'a, Ctx> {
|
||||||
|
let point = &self
|
||||||
|
.points
|
||||||
|
.get(address.index)
|
||||||
|
.expect("CastResolved received an invalid address.");
|
||||||
|
if point.point != address.point {
|
||||||
|
panic!("CastResolved received an invalid address.")
|
||||||
|
}
|
||||||
|
Ctx::T::fmap(
|
||||||
|
|resolved| match resolved {
|
||||||
|
Ok(mentionable) => {
|
||||||
|
let mut vec = Vec::new();
|
||||||
|
mentionable.serialize(&mut vec);
|
||||||
|
let resolver: Rc<dyn Resolver<'a, Ctx>> = Rc::new(CastResolver {
|
||||||
|
points: mentionable.points(),
|
||||||
|
});
|
||||||
|
Ok((vec, resolver))
|
||||||
|
}
|
||||||
|
Err(error) => Err(match error {
|
||||||
|
ResolutionError::Lookup(lookup_error) => lookup_error,
|
||||||
|
ResolutionError::Parse(parse_error) => parse_error.into(),
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
point.resolve(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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: From<TypelessError<'a>>,
|
||||||
|
{
|
||||||
|
/// .
|
||||||
|
///
|
||||||
|
/// # Errors
|
||||||
|
///
|
||||||
|
/// This function will return an error if .
|
||||||
|
pub fn cast<A: Mentionable<'a, Ctx>>(&self, factory: A::Fctr) -> CastResult<'a, Ctx, A> {
|
||||||
|
let mut vec = Vec::new();
|
||||||
|
self.serialize(&mut vec);
|
||||||
|
factory.parse_slice(
|
||||||
|
&vec,
|
||||||
|
Rc::new(CastResolver {
|
||||||
|
points: self.points(),
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
77
src/std/nullable.rs
Normal file
77
src/std/nullable.rs
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
use crate::core::*;
|
||||||
|
use crate::std::*;
|
||||||
|
|
||||||
|
enum Nullable<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> {
|
||||||
|
Null(A::Fctr),
|
||||||
|
NotNull(Point<'a, Ctx, A>),
|
||||||
|
}
|
||||||
|
|
||||||
|
struct NullableFactory<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> {
|
||||||
|
factory: A::Fctr,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> Serializable for Nullable<'a, Ctx, A> {
|
||||||
|
fn serialize(&self, serializer: &mut dyn Serializer) {
|
||||||
|
serializer.write(match self {
|
||||||
|
Nullable::Null(_) => &HASH_ZEROS,
|
||||||
|
Nullable::NotNull(point) => &point.point,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> Mentionable<'a, Ctx> for Nullable<'a, Ctx, A> {
|
||||||
|
type Fctr = NullableFactory<'a, Ctx, A>;
|
||||||
|
|
||||||
|
fn factory(&self) -> Self::Fctr {
|
||||||
|
match self {
|
||||||
|
Nullable::Null(factory) => NullableFactory {
|
||||||
|
factory: factory.clone(),
|
||||||
|
},
|
||||||
|
Nullable::NotNull(point) => NullableFactory {
|
||||||
|
factory: point.origin.factory(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn points(&self) -> Vec<Point<'a, Ctx, TypelessMentionable<'a, Ctx>>> {
|
||||||
|
match self {
|
||||||
|
Nullable::Null(_) => vec![],
|
||||||
|
Nullable::NotNull(point) => vec![point.typeless()],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> Clone for NullableFactory<'a, Ctx, A> {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
Self {
|
||||||
|
factory: self.factory.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> Factory<'a, Ctx>
|
||||||
|
for NullableFactory<'a, Ctx, A>
|
||||||
|
{
|
||||||
|
type Mtbl = Nullable<'a, Ctx, A>;
|
||||||
|
|
||||||
|
type ParseError = PointParseError;
|
||||||
|
|
||||||
|
fn deserialize(
|
||||||
|
&self,
|
||||||
|
deserializer: &mut dyn Deserializer,
|
||||||
|
resolver: std::rc::Rc<dyn Resolver<'a, Ctx>>,
|
||||||
|
) -> ParseResult<'a, Ctx, Self> {
|
||||||
|
let point = deserializer.read_n_const::<HASH_SIZE>()?;
|
||||||
|
let factory = self.factory.clone();
|
||||||
|
Ok(if point == HASH_ZEROS {
|
||||||
|
Nullable::Null(factory)
|
||||||
|
} else {
|
||||||
|
let mut addresses = Addresses::start();
|
||||||
|
Nullable::NotNull(addresses.next_point(deserializer, resolver, factory)?)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn unexpected_tail(&self, tail: &[u8]) -> Self::ParseError {
|
||||||
|
PointParseError::WrongLength(HASH_SIZE + tail.len())
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user