extract resolution
This commit is contained in:
parent
1b00d2c326
commit
7951425738
158
src/core.rs
158
src/core.rs
@ -3,11 +3,13 @@
|
|||||||
//! Allows for more generic behaviour via [`Context`], as opposed to original async-only.
|
//! Allows for more generic behaviour via [`Context`], as opposed to original async-only.
|
||||||
|
|
||||||
mod hashing;
|
mod hashing;
|
||||||
|
mod resolution;
|
||||||
mod serialization;
|
mod serialization;
|
||||||
mod slice_deserializer;
|
mod slice_deserializer;
|
||||||
mod typeless;
|
mod typeless;
|
||||||
|
|
||||||
pub use hashing::*;
|
pub use hashing::*;
|
||||||
|
pub use resolution::*;
|
||||||
pub use serialization::*;
|
pub use serialization::*;
|
||||||
pub use slice_deserializer::*;
|
pub use slice_deserializer::*;
|
||||||
pub use typeless::*;
|
pub use typeless::*;
|
||||||
@ -28,28 +30,9 @@ pub trait Context {
|
|||||||
fn hash(s: &[u8]) -> Hash;
|
fn hash(s: &[u8]) -> Hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Failure yielded by [`Origin`].
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub enum ResolutionError<L, P> {
|
|
||||||
Lookup(L),
|
|
||||||
Parse(P),
|
|
||||||
}
|
|
||||||
|
|
||||||
/// See [`ResolutionResult`].
|
|
||||||
pub type ResolutionFailure<'a, Ctx, A> = ResolutionError<
|
|
||||||
<Ctx as Context>::LookupError<'a>,
|
|
||||||
<<A as Mentionable<'a, Ctx>>::Fctr as Factory<'a, Ctx>>::ParseError,
|
|
||||||
>;
|
|
||||||
|
|
||||||
/// Result yielded by [`Origin`].
|
|
||||||
pub type ResolutionResult<'a, Ctx, A> = Result<Rc<A>, ResolutionFailure<'a, Ctx, A>>;
|
|
||||||
|
|
||||||
/// Helper alias for [`WeakFunctor::F`] of [`Context::T`].
|
/// Helper alias for [`WeakFunctor::F`] of [`Context::T`].
|
||||||
pub type Wrapped<'a, Ctx, A> = <<Ctx as Context>::T as WeakFunctor>::F<'a, A>;
|
pub type Wrapped<'a, Ctx, A> = <<Ctx as Context>::T as WeakFunctor>::F<'a, A>;
|
||||||
|
|
||||||
/// Wrapped result returned by [`Origin`].
|
|
||||||
pub type Resolution<'a, Ctx, A> = Wrapped<'a, Ctx, ResolutionResult<'a, Ctx, A>>;
|
|
||||||
|
|
||||||
/// Fundamental trait for ADN objects.
|
/// Fundamental trait for ADN objects.
|
||||||
pub trait Mentionable<'a, Ctx: 'a + Context>: 'a + Serializable {
|
pub trait Mentionable<'a, Ctx: 'a + Context>: 'a + Serializable {
|
||||||
/// Type of the associated factory.
|
/// Type of the associated factory.
|
||||||
@ -77,28 +60,6 @@ pub trait Mentionable<'a, Ctx: 'a + Context>: 'a + Serializable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Short-hand for the type of values returned by [`Resolver::resolve`].
|
|
||||||
pub type HashResolution<'a, Ctx> = Wrapped<
|
|
||||||
'a,
|
|
||||||
Ctx,
|
|
||||||
Result<(Vec<u8>, Rc<dyn Resolver<'a, Ctx>>), <Ctx as Context>::LookupError<'a>>,
|
|
||||||
>;
|
|
||||||
|
|
||||||
/// Value accepted by [`Resolver::resolve`]. Includes index to make it order-sensitive.
|
|
||||||
#[derive(Clone, Copy, Debug)]
|
|
||||||
pub struct Address {
|
|
||||||
pub point: Hash,
|
|
||||||
/// Index of the point in the [`Mentionable::points()`].
|
|
||||||
pub index: usize,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Trait representing the "rainbow table" behaviour.
|
|
||||||
pub trait Resolver<'a, Ctx: 'a + Context>: 'a {
|
|
||||||
/// Successfully returned value should be the inverse of the point passed
|
|
||||||
/// with topology header ([`Mentionable::topology()`]) omitted.
|
|
||||||
fn resolve(self: Rc<Self>, address: Address) -> HashResolution<'a, Ctx>;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Short-hand for the type of vaalues returned by [`Factory::deserialize`].
|
/// Short-hand for the type of vaalues returned by [`Factory::deserialize`].
|
||||||
pub type ParseResult<'a, Ctx, F> =
|
pub type ParseResult<'a, Ctx, F> =
|
||||||
Result<<F as Factory<'a, Ctx>>::Mtbl, <F as Factory<'a, Ctx>>::ParseError>;
|
Result<<F as Factory<'a, Ctx>>::Mtbl, <F as Factory<'a, Ctx>>::ParseError>;
|
||||||
@ -152,111 +113,6 @@ impl<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> Point<'a, Ctx, A> {
|
|||||||
pub fn resolve(&self) -> Resolution<'a, Ctx, A> {
|
pub fn resolve(&self) -> Resolution<'a, Ctx, A> {
|
||||||
self.origin.clone().resolve()
|
self.origin.clone().resolve()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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,
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 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 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Extension trait for factories.
|
/// Extension trait for factories.
|
||||||
@ -268,13 +124,3 @@ pub trait ExtFactory<'a, Ctx: 'a + Context>: Factory<'a, Ctx> {
|
|||||||
resolver: Rc<dyn Resolver<'a, Ctx>>,
|
resolver: Rc<dyn Resolver<'a, Ctx>>,
|
||||||
) -> ParseResult<'a, Ctx, Self>;
|
) -> 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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
159
src/core/resolution.rs
Normal file
159
src/core/resolution.rs
Normal file
@ -0,0 +1,159 @@
|
|||||||
|
use super::*;
|
||||||
|
|
||||||
|
/// Failure yielded by [`Origin`].
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum ResolutionError<L, P> {
|
||||||
|
Lookup(L),
|
||||||
|
Parse(P),
|
||||||
|
}
|
||||||
|
|
||||||
|
/// See [`ResolutionResult`].
|
||||||
|
pub type ResolutionFailure<'a, Ctx, A> = ResolutionError<
|
||||||
|
<Ctx as Context>::LookupError<'a>,
|
||||||
|
<<A as Mentionable<'a, Ctx>>::Fctr as Factory<'a, Ctx>>::ParseError,
|
||||||
|
>;
|
||||||
|
|
||||||
|
/// Result yielded by [`Origin`].
|
||||||
|
pub type ResolutionResult<'a, Ctx, A> = Result<Rc<A>, ResolutionFailure<'a, Ctx, A>>;
|
||||||
|
|
||||||
|
/// Wrapped result returned by [`Origin`].
|
||||||
|
pub type Resolution<'a, Ctx, A> = Wrapped<'a, Ctx, ResolutionResult<'a, Ctx, A>>;
|
||||||
|
|
||||||
|
/// Short-hand for the type of values returned by [`Resolver::resolve`].
|
||||||
|
pub type HashResolution<'a, Ctx> = Wrapped<
|
||||||
|
'a,
|
||||||
|
Ctx,
|
||||||
|
Result<(Vec<u8>, Rc<dyn Resolver<'a, Ctx>>), <Ctx as Context>::LookupError<'a>>,
|
||||||
|
>;
|
||||||
|
|
||||||
|
/// Value accepted by [`Resolver::resolve`]. Includes index to make it order-sensitive.
|
||||||
|
#[derive(Clone, Copy, Debug)]
|
||||||
|
pub struct Address {
|
||||||
|
pub point: Hash,
|
||||||
|
/// Index of the point in the [`Mentionable::points()`].
|
||||||
|
pub index: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Trait representing the "rainbow table" behaviour.
|
||||||
|
pub trait Resolver<'a, Ctx: 'a + Context>: 'a {
|
||||||
|
/// Successfully returned value should be the inverse of the point passed
|
||||||
|
/// with topology header ([`Mentionable::topology()`]) omitted.
|
||||||
|
fn resolve(self: Rc<Self>, address: Address) -> HashResolution<'a, Ctx>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> Point<'a, Ctx, A> {
|
||||||
|
/// 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,
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 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 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user