addresses moved to core
This commit is contained in:
parent
8ebe30cd65
commit
29d0eb3ee2
185
src/core.rs
185
src/core.rs
@ -2,7 +2,7 @@
|
||||
//! Brings [`Mentionable`]/[`Factory`]/[`Origin`] concepts from the original implementation in Python.
|
||||
//! Allows for more generic behaviour via [`Context`], as opposed to original async-only.
|
||||
|
||||
use std::{error::Error, fmt::Display, rc::Rc};
|
||||
use std::{cmp::min, error::Error, fmt::Display, rc::Rc};
|
||||
|
||||
use crate::func::*;
|
||||
|
||||
@ -155,6 +155,7 @@ pub trait Factory<'a, Ctx: 'a + Context>: Clone + 'a {
|
||||
&self,
|
||||
deserializer: &mut dyn Deserializer,
|
||||
resolver: Rc<dyn Resolver<'a, Ctx>>,
|
||||
addresses: &mut Addresses,
|
||||
) -> ParseResult<'a, Ctx, Self>;
|
||||
/// Called by finite stream parsers if there's any data left.
|
||||
fn unexpected_tail(&self, tail: &[u8]) -> Self::ParseError;
|
||||
@ -231,6 +232,22 @@ impl<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> Point<'a, Ctx, A> {
|
||||
LocalOrigin::from(mentionable),
|
||||
)
|
||||
}
|
||||
|
||||
/// Make a [Point] from an [Address].
|
||||
pub fn from_address(
|
||||
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>> From<A> for Point<'a, Ctx, A> {
|
||||
@ -251,8 +268,8 @@ pub struct TypelessMentionable<'a, Ctx: 'a + Context> {
|
||||
|
||||
type TypelessParsed<'a, Ctx> = Result<TypelessMentionable<'a, Ctx>, Box<dyn 'a + Error>>;
|
||||
|
||||
type TypelessDeserialize<'a, Ctx> =
|
||||
dyn 'a + Fn(&mut dyn Deserializer, Rc<dyn Resolver<'a, Ctx>>) -> TypelessParsed<'a, Ctx>;
|
||||
type TypelessDeserialize<'a, Ctx> = dyn 'a
|
||||
+ Fn(&mut dyn Deserializer, Rc<dyn Resolver<'a, Ctx>>, &mut Addresses) -> TypelessParsed<'a, Ctx>;
|
||||
|
||||
type TypelessUnexpectedTail<'a> = dyn 'a + Fn(&[u8]) -> TypelessError<'a>;
|
||||
|
||||
@ -318,8 +335,9 @@ impl<'a, Ctx: 'a + Context> Factory<'a, Ctx> for TypelessFactory<'a, Ctx> {
|
||||
&self,
|
||||
deserializer: &mut dyn Deserializer,
|
||||
resolver: Rc<dyn Resolver<'a, Ctx>>,
|
||||
addresses: &mut Addresses,
|
||||
) -> ParseResult<'a, Ctx, Self> {
|
||||
match (self.t_deserialize)(deserializer, resolver) {
|
||||
match (self.t_deserialize)(deserializer, resolver, addresses) {
|
||||
Ok(mentionable) => Ok(mentionable),
|
||||
Err(error) => Err(TypelessError(error)),
|
||||
}
|
||||
@ -348,8 +366,8 @@ impl<'a, Ctx: 'a + Context> TypelessFactory<'a, Ctx> {
|
||||
pub fn from_typed<F: Factory<'a, Ctx>>(factory: F) -> Self {
|
||||
let tail_factory = factory.clone();
|
||||
TypelessFactory {
|
||||
t_deserialize: Rc::new(move |deserializer, resolver| {
|
||||
match factory.deserialize(deserializer, resolver) {
|
||||
t_deserialize: Rc::new(move |deserializer, resolver, addresses| {
|
||||
match factory.deserialize(deserializer, resolver, addresses) {
|
||||
Ok(mentionable) => Ok(TypelessMentionable::from_typed(Rc::new(mentionable))),
|
||||
Err(error) => Err(Box::new(error)),
|
||||
}
|
||||
@ -366,3 +384,158 @@ impl<'a> TypelessError<'a> {
|
||||
TypelessError(Box::new(error))
|
||||
}
|
||||
}
|
||||
|
||||
/// Preferred way to parse [Point]s off of a [Serializer].
|
||||
pub struct Addresses {
|
||||
current: usize,
|
||||
}
|
||||
|
||||
impl Addresses {
|
||||
/// Read the next [Address].
|
||||
pub 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)
|
||||
}
|
||||
|
||||
/// Read the next [Point].
|
||||
pub 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_address(
|
||||
self.next(deserializer)?,
|
||||
factory,
|
||||
resolver,
|
||||
))
|
||||
}
|
||||
|
||||
/// Start reading the [Address]es.
|
||||
fn start() -> Self {
|
||||
Addresses { current: 0 }
|
||||
}
|
||||
}
|
||||
|
||||
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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
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, &mut Addresses::start())?;
|
||||
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 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
|
||||
}
|
||||
}
|
||||
|
170
src/std.rs
170
src/std.rs
@ -1,10 +1,11 @@
|
||||
//! Standard extensions to [`crate::core`].
|
||||
|
||||
pub mod atomic;
|
||||
pub mod cast;
|
||||
pub mod collections;
|
||||
pub mod inlining;
|
||||
pub mod nullable;
|
||||
|
||||
use std::cmp::min;
|
||||
use std::{error::Error, fmt::Display, rc::Rc};
|
||||
|
||||
use crate::core::*;
|
||||
@ -161,62 +162,12 @@ impl From<&[u8]> for PointParseError {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> Point<'a, Ctx, A> {
|
||||
fn from_address(
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
pub 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_address(
|
||||
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> {
|
||||
type Mtbl = Point<'a, Ctx, F::Mtbl>;
|
||||
|
||||
@ -226,8 +177,8 @@ impl<'a, Ctx: 'a + Context, F: Factory<'a, Ctx>> Factory<'a, Ctx> for PointFacto
|
||||
&self,
|
||||
deserializer: &mut dyn Deserializer,
|
||||
resolver: Rc<dyn Resolver<'a, Ctx>>,
|
||||
addresses: &mut Addresses,
|
||||
) -> ParseResult<'a, Ctx, Self> {
|
||||
let mut addresses = Addresses::start();
|
||||
Ok(addresses.next_point(deserializer, resolver, self.factory.clone())?)
|
||||
}
|
||||
|
||||
@ -236,121 +187,6 @@ impl<'a, Ctx: 'a + Context, F: Factory<'a, Ctx>> Factory<'a, Ctx> for PointFacto
|
||||
}
|
||||
}
|
||||
|
||||
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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Address {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.write_fmt(format_args!("{}@{}", hex::encode(self.point), self.index))
|
||||
|
@ -1,7 +1,10 @@
|
||||
//! Provides [Atomic]-[Mentionable] interface.
|
||||
|
||||
use std::ops::Deref;
|
||||
|
||||
use super::*;
|
||||
|
||||
/// Generic implementation of a [Mentionable] for [Atomic]s.
|
||||
pub struct AtomicObject<A: Atomic> {
|
||||
atomic: A,
|
||||
}
|
||||
@ -46,12 +49,14 @@ impl<'a, Ctx: 'a + Context, A: Atomic> Mentionable<'a, Ctx> for AtomicObject<A>
|
||||
fn points(&self, _points: &mut Vec<Point<'a, Ctx, TypelessMentionable<'a, Ctx>>>) {}
|
||||
}
|
||||
|
||||
/// Generic implementation of a factory for [Atomic]s.
|
||||
pub struct AtomicFactory<A: Atomic>(PhantomData<A>);
|
||||
/// Generic implementation of a [Factory] for [Atomic]s.
|
||||
pub struct AtomicFactory<A: Atomic> {
|
||||
_pd: PhantomData<A>,
|
||||
}
|
||||
|
||||
impl<A: Atomic> AtomicFactory<A> {
|
||||
fn new() -> Self {
|
||||
AtomicFactory(PhantomData)
|
||||
AtomicFactory { _pd: PhantomData }
|
||||
}
|
||||
}
|
||||
|
||||
@ -70,6 +75,7 @@ impl<'a, Ctx: 'a + Context, A: Atomic> Factory<'a, Ctx> for AtomicFactory<A> {
|
||||
&self,
|
||||
deserializer: &mut dyn Deserializer,
|
||||
_resolver: Rc<dyn Resolver<'a, Ctx>>,
|
||||
_addresses: &mut Addresses,
|
||||
) -> ParseResult<'a, Ctx, Self> {
|
||||
Ok(A::deserialize(deserializer)?.into())
|
||||
}
|
||||
|
@ -1,3 +1,5 @@
|
||||
//! [`Pair`] implementation based on [`StaticPair`].
|
||||
|
||||
use std::error::Error;
|
||||
use std::fmt::Display;
|
||||
|
||||
@ -18,7 +20,7 @@ impl<A: Serializable, B: Serializable> StaticPairSerializable for Pair<A, B> {
|
||||
type SA = A;
|
||||
type SB = B;
|
||||
|
||||
fn s_elements(&self) -> (&Self::SA, &Self::SB) {
|
||||
fn elements(&self) -> (&Self::SA, &Self::SB) {
|
||||
(&self.a, &self.b)
|
||||
}
|
||||
}
|
||||
@ -89,8 +91,4 @@ where
|
||||
b: self.b.factory(),
|
||||
}
|
||||
}
|
||||
|
||||
fn elements(&self) -> (&Self::A, &Self::B) {
|
||||
(&self.a, &self.b)
|
||||
}
|
||||
}
|
||||
|
@ -88,16 +88,23 @@ impl<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> Factory<'a, Ctx>
|
||||
&self,
|
||||
deserializer: &mut dyn Deserializer,
|
||||
resolver: Rc<dyn Resolver<'a, Ctx>>,
|
||||
addresses: &mut Addresses,
|
||||
) -> ParseResult<'a, Ctx, Self> {
|
||||
let rest =
|
||||
match NullableFactory::new(self.clone()).deserialize(deserializer, resolver.clone()) {
|
||||
Ok(rest) => rest,
|
||||
Err(ppe) => {
|
||||
return Err(StackParseError::Point(ppe));
|
||||
}
|
||||
};
|
||||
let rest = match NullableFactory::new(self.clone()).deserialize(
|
||||
deserializer,
|
||||
resolver.clone(),
|
||||
addresses,
|
||||
) {
|
||||
Ok(rest) => rest,
|
||||
Err(ppe) => {
|
||||
return Err(StackParseError::Point(ppe));
|
||||
}
|
||||
};
|
||||
let element = Rc::new(
|
||||
match self.element_factory.deserialize(deserializer, resolver) {
|
||||
match self
|
||||
.element_factory
|
||||
.deserialize(deserializer, resolver, addresses)
|
||||
{
|
||||
Ok(element) => element,
|
||||
Err(epe) => {
|
||||
return Err(StackParseError::Element(epe));
|
||||
|
@ -1,3 +1,5 @@
|
||||
//! Traits to better express parsing semantics.
|
||||
|
||||
pub mod static_pair;
|
||||
|
||||
use super::atomic::atomic_object::*;
|
||||
@ -5,28 +7,44 @@ use super::atomic::*;
|
||||
use crate::core::*;
|
||||
use crate::std::*;
|
||||
|
||||
/// This factory should return an error on EOF.
|
||||
pub trait InlineableFactory {}
|
||||
|
||||
/// This factory always reads the same amount of bytes or returns error.
|
||||
pub trait FixedSizeFactory: InlineableFactory {
|
||||
/// For [`ConstSizeFactory`] this must return [`ConstSizeFactory::SIZE`].
|
||||
fn size(&self) -> usize;
|
||||
}
|
||||
|
||||
/// Compile-time analogue of [`FixedSizeFactory`].
|
||||
pub trait ConstSizeFactory: FixedSizeFactory {
|
||||
/// Must be equal to [`FixedSizeFactory::size()`].
|
||||
const SIZE: usize;
|
||||
}
|
||||
|
||||
/// Object analogue of [`InlineableFactory`].
|
||||
pub trait InlineableObject<'a, Ctx: 'a + Context>: 'a {}
|
||||
|
||||
/// Object analogue of [`FixedSizeFactory`].
|
||||
pub trait FixedSizeObject<'a, Ctx: 'a + Context>: InlineableObject<'a, Ctx> {
|
||||
/// For [`ConstSizeObject`] this must return [`ConstSizeObject::SIZE`].
|
||||
fn size(&self) -> usize;
|
||||
}
|
||||
|
||||
/// Object analogue of [`ConstSizeFactory`].
|
||||
pub trait ConstSizeObject<'a, Ctx: 'a + Context>: FixedSizeObject<'a, Ctx> {
|
||||
/// Must be equal to [`FixedSizeObject::size()`].
|
||||
const SIZE: usize;
|
||||
}
|
||||
|
||||
/// Atomic analogue of [`InlineableFactory`]/[`InlineableObject`].
|
||||
pub trait InlineableAtomic {}
|
||||
|
||||
/// Atomic analogue of [`ConstSizeFactory`]/[`ConstSizeObject`].
|
||||
///
|
||||
/// Note: `FixedSizeAtomic` doesn't exist because it would
|
||||
/// either be const anyway
|
||||
/// or have a very undesireable implementation.
|
||||
pub trait ConstSizeAtomic: InlineableAtomic {
|
||||
const SIZE: usize;
|
||||
}
|
||||
@ -64,6 +82,7 @@ where
|
||||
const SIZE: usize = A::Fctr::SIZE;
|
||||
}
|
||||
|
||||
/// Error returned by [`CheckedParse::deserialize_checked`]/[`CheckedSerialize::serialize_checked`].
|
||||
#[derive(Debug)]
|
||||
pub struct SizeError {
|
||||
expected: usize,
|
||||
@ -81,6 +100,7 @@ impl Display for SizeError {
|
||||
|
||||
impl Error for SizeError {}
|
||||
|
||||
/// Wrapper for [`SizeError`]/[`Factory::ParseError`].
|
||||
#[derive(Debug)]
|
||||
pub enum CheckedParseError<P: Error> {
|
||||
Parse(P),
|
||||
@ -104,18 +124,24 @@ impl<P: Error> From<P> for CheckedParseError<P> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returned by [`CheckedParse::deserialize_checked`].
|
||||
pub type CheckedParseResult<'a, Ctx, F> =
|
||||
Result<<F as Factory<'a, Ctx>>::Mtbl, CheckedParseError<<F as Factory<'a, Ctx>>::ParseError>>;
|
||||
|
||||
/// Extension trait for factories that ensures fixed size read.
|
||||
pub trait CheckedParse<'a, Ctx: 'a + Context>: FixedSizeFactory + Factory<'a, Ctx> {
|
||||
/// Verify proper read length using [`Deserializer::tell`].
|
||||
fn deserialize_checked(
|
||||
&self,
|
||||
deserializer: &mut dyn Deserializer,
|
||||
resolver: Rc<dyn Resolver<'a, Ctx>>,
|
||||
addresses: &mut Addresses,
|
||||
) -> CheckedParseResult<'a, Ctx, Self>;
|
||||
}
|
||||
|
||||
/// Extension trait for factories that ensures fixed size write.
|
||||
pub trait CheckedSerialize<'a, Ctx: 'a + Context>: Serializable + FixedSizeObject<'a, Ctx> {
|
||||
/// Verify proper write length using [`Serializer::tell`].
|
||||
fn serialize_checked(&self, serializer: &mut dyn Serializer) -> Result<(), SizeError>;
|
||||
}
|
||||
|
||||
@ -124,10 +150,11 @@ impl<'a, Ctx: 'a + Context, F: FixedSizeFactory + Factory<'a, Ctx>> CheckedParse
|
||||
&self,
|
||||
deserializer: &mut dyn Deserializer,
|
||||
resolver: Rc<dyn Resolver<'a, Ctx>>,
|
||||
addresses: &mut Addresses,
|
||||
) -> CheckedParseResult<'a, Ctx, Self> {
|
||||
let expected_size = self.size();
|
||||
let start = deserializer.tell();
|
||||
let result = self.deserialize(deserializer, resolver)?;
|
||||
let result = self.deserialize(deserializer, resolver, addresses)?;
|
||||
let end = deserializer.tell();
|
||||
let received_size = end - start;
|
||||
if received_size == expected_size {
|
||||
@ -161,6 +188,9 @@ impl<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx> + FixedSizeObject<'a, Ctx>>
|
||||
}
|
||||
}
|
||||
|
||||
/// Trait useful for objects which aren't influenced by
|
||||
/// whether some other type (for example, a generic parameter type)
|
||||
/// is fixed-size or not.
|
||||
pub trait AlwaysFixedSize {
|
||||
fn _size(&self) -> usize;
|
||||
}
|
||||
@ -173,6 +203,7 @@ impl<F: AlwaysFixedSize> FixedSizeFactory for F {
|
||||
}
|
||||
}
|
||||
|
||||
/// Compile-time analogue of [`AlwaysFixedSize`].
|
||||
pub trait AlwaysConstSize {
|
||||
const _SIZE: usize;
|
||||
}
|
||||
|
@ -1,39 +1,66 @@
|
||||
//! Generic implementation for objects that are structured
|
||||
//! like a pair of two other objects.
|
||||
|
||||
use std::ops::Deref;
|
||||
|
||||
use super::*;
|
||||
use crate::core::*;
|
||||
|
||||
/// Trait to represent serialisation of object's data.
|
||||
/// Due to serialisation being [Context]-free in RADN,
|
||||
/// this functionality is in a separate trait.
|
||||
pub trait StaticPairSerializable {
|
||||
/// First element's type. Must equal [`StaticPair::A`].
|
||||
type SA: Serializable;
|
||||
/// Second element's type. Must equal [`StaticPair::B`].
|
||||
type SB: Serializable;
|
||||
|
||||
fn s_elements(&self) -> (&Self::SA, &Self::SB);
|
||||
/// Borrow both elements.
|
||||
fn elements(&self) -> (&Self::SA, &Self::SB);
|
||||
}
|
||||
|
||||
/// Trait to be implemented on object data.
|
||||
///
|
||||
/// [`StaticPair::FA`]/[`StaticPair::FB`] are required members
|
||||
/// for clarity and [`StaticPair`]'s simpler implementation
|
||||
/// at the cost of having to specify two extra fields.
|
||||
///
|
||||
/// Note: [`StaticPair::FA`] requires [`InlineableFactory`] be implemented.
|
||||
pub trait StaticPair<'a, Ctx: 'a + Context>:
|
||||
'a + StaticPairSerializable<SA = Self::A, SB = Self::B>
|
||||
{
|
||||
/// [Factory] data. May, depending on the usecase, include factory (factories) on the element(s).
|
||||
type FactoryData: 'a + Clone;
|
||||
/// First element's type. Must equal [`StaticPairSerializable::SA`].
|
||||
type A: Mentionable<'a, Ctx, Fctr = Self::FA>;
|
||||
/// Second element's type. Must equal [`StaticPairSerializable::SB`].
|
||||
type B: Mentionable<'a, Ctx, Fctr = Self::FB>;
|
||||
/// First element's factory.
|
||||
type FA: Factory<'a, Ctx, Mtbl = Self::A> + InlineableFactory;
|
||||
/// Second element's factory.
|
||||
type FB: Factory<'a, Ctx, Mtbl = Self::B>;
|
||||
/// See [Factory::ParseError].
|
||||
type ParseError: 'a + Error;
|
||||
|
||||
/// Borrow both elements' factories.
|
||||
fn factories(factory_data: &Self::FactoryData) -> (&Self::FA, &Self::FB);
|
||||
/// Construct the object from the elements.
|
||||
fn from_parsed(factory_data: &Self::FactoryData, a: Self::A, b: Self::B) -> Self;
|
||||
/// Regularise the error returned while parsing the first element.
|
||||
fn from_error_a(
|
||||
factory_data: &Self::FactoryData,
|
||||
error: <Self::FA as Factory<'a, Ctx>>::ParseError,
|
||||
) -> Self::ParseError;
|
||||
/// Regularise the error returned while parsing the second element.
|
||||
fn from_error_b(
|
||||
factory_data: &Self::FactoryData,
|
||||
error: <Self::FB as Factory<'a, Ctx>>::ParseError,
|
||||
) -> Self::ParseError;
|
||||
/// Derive factory data from the object data.
|
||||
fn factory_data(&self) -> Self::FactoryData;
|
||||
fn elements(&self) -> (&Self::A, &Self::B);
|
||||
}
|
||||
|
||||
/// Generic implementation of a [Mentionable] for [StaticPair]s.
|
||||
pub struct StaticPairObject<SP> {
|
||||
pair: SP,
|
||||
}
|
||||
@ -58,13 +85,14 @@ impl<SP> Deref for StaticPairObject<SP> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Generic implementation of a [Factory] for [StaticPair]s.
|
||||
pub struct StaticPairFactory<'a, Ctx: 'a + Context, SP: StaticPair<'a, Ctx>> {
|
||||
factory_data: SP::FactoryData,
|
||||
}
|
||||
|
||||
impl<SP: StaticPairSerializable> Serializable for StaticPairObject<SP> {
|
||||
fn serialize(&self, serializer: &mut dyn Serializer) {
|
||||
let (a, b) = self.pair.s_elements();
|
||||
let (a, b) = self.pair.elements();
|
||||
a.serialize(serializer);
|
||||
b.serialize(serializer);
|
||||
}
|
||||
@ -105,13 +133,14 @@ impl<'a, Ctx: 'a + Context, SP: StaticPair<'a, Ctx>> Factory<'a, Ctx>
|
||||
&self,
|
||||
deserializer: &mut dyn Deserializer,
|
||||
resolver: Rc<dyn Resolver<'a, Ctx>>,
|
||||
addresses: &mut Addresses,
|
||||
) -> ParseResult<'a, Ctx, Self> {
|
||||
let (fa, fb) = SP::factories(&self.factory_data);
|
||||
let a: SP::A = match fa.deserialize(deserializer, resolver.clone()) {
|
||||
let a: SP::A = match fa.deserialize(deserializer, resolver.clone(), addresses) {
|
||||
Ok(a) => a,
|
||||
Err(error) => return Err(SP::from_error_a(&self.factory_data, error)),
|
||||
};
|
||||
let b: SP::B = match fb.deserialize(deserializer, resolver) {
|
||||
let b: SP::B = match fb.deserialize(deserializer, resolver, addresses) {
|
||||
Ok(b) => b,
|
||||
Err(error) => return Err(SP::from_error_b(&self.factory_data, error)),
|
||||
};
|
||||
|
@ -67,8 +67,8 @@ impl<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> Factory<'a, Ctx>
|
||||
&self,
|
||||
deserializer: &mut dyn Deserializer,
|
||||
resolver: std::rc::Rc<dyn Resolver<'a, Ctx>>,
|
||||
addresses: &mut Addresses,
|
||||
) -> ParseResult<'a, Ctx, Self> {
|
||||
let mut addresses = Addresses::start();
|
||||
let factory = self.factory.clone();
|
||||
let address = addresses.next(deserializer)?;
|
||||
Ok(if address.point == HASH_ZEROS {
|
||||
|
Loading…
Reference in New Issue
Block a user