extract typeless and local_origin
This commit is contained in:
parent
5ae43e60b2
commit
9e578b6610
200
src/core.rs
200
src/core.rs
@ -2,6 +2,10 @@
|
||||
//! Brings [`Mentionable`]/[`Factory`]/[`Origin`] concepts from the original implementation in Python.
|
||||
//! Allows for more generic behaviour via [`Context`], as opposed to original async-only.
|
||||
|
||||
pub mod typeless;
|
||||
|
||||
pub use typeless::*;
|
||||
|
||||
use std::{cmp::min, error::Error, fmt::Display, rc::Rc};
|
||||
|
||||
use crate::func::*;
|
||||
@ -61,16 +65,6 @@ pub trait Serializer {
|
||||
fn tell(&self) -> usize;
|
||||
}
|
||||
|
||||
impl Serializer for Vec<u8> {
|
||||
fn write(&mut self, buf: &[u8]) {
|
||||
self.extend(buf);
|
||||
}
|
||||
|
||||
fn tell(&self) -> usize {
|
||||
self.len()
|
||||
}
|
||||
}
|
||||
|
||||
/// See [`Serializer`].
|
||||
pub trait Serializable {
|
||||
/// Expected to use [`Serializer::write`].
|
||||
@ -171,26 +165,6 @@ pub trait Origin<'a, Ctx: 'a + Context>: 'a {
|
||||
fn resolve(self: Rc<Self>) -> Resolution<'a, Ctx, Self::Mtbl>;
|
||||
}
|
||||
|
||||
struct LocalOrigin<A>(Rc<A>);
|
||||
|
||||
impl<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> Origin<'a, Ctx> for LocalOrigin<A> {
|
||||
type Mtbl = A;
|
||||
|
||||
fn factory(&self) -> A::Fctr {
|
||||
self.0.factory()
|
||||
}
|
||||
|
||||
fn resolve(self: Rc<Self>) -> Resolution<'a, Ctx, Self::Mtbl> {
|
||||
Ctx::T::pure(Ok(self.0.clone()))
|
||||
}
|
||||
}
|
||||
|
||||
impl<A> From<A> for LocalOrigin<A> {
|
||||
fn from(value: A) -> Self {
|
||||
LocalOrigin(value.into())
|
||||
}
|
||||
}
|
||||
|
||||
/// The main way to represent a reference in ADN.
|
||||
pub struct Point<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> {
|
||||
pub point: Hash,
|
||||
@ -207,32 +181,11 @@ impl<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> Clone for Point<'a, Ctx, A>
|
||||
}
|
||||
|
||||
impl<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> Point<'a, Ctx, A> {
|
||||
fn prepare_bytes_for_hashing(mentioned: &A) -> Vec<u8> {
|
||||
let mut vec = mentioned.topology().to_vec();
|
||||
mentioned.serialize(&mut vec);
|
||||
vec
|
||||
}
|
||||
|
||||
fn from_fields(point: Hash, origin: Rc<dyn Origin<'a, Ctx, Mtbl = A>>) -> Self {
|
||||
Point { point, origin }
|
||||
}
|
||||
|
||||
fn from_values<O: Origin<'a, Ctx, Mtbl = A>>(point: Hash, origin: O) -> Self {
|
||||
Self::from_fields(point, Rc::new(origin))
|
||||
}
|
||||
|
||||
/// See [`Origin::resolve`].
|
||||
pub fn resolve(&self) -> Resolution<'a, Ctx, A> {
|
||||
self.origin.clone().resolve()
|
||||
}
|
||||
|
||||
fn from_mentionable(mentionable: A) -> Self {
|
||||
Self::from_values(
|
||||
Ctx::hash(Self::prepare_bytes_for_hashing(&mentionable).as_slice()),
|
||||
LocalOrigin::from(mentionable),
|
||||
)
|
||||
}
|
||||
|
||||
/// Make a [Point] from an [Address].
|
||||
pub fn from_address(
|
||||
address: Address,
|
||||
@ -250,141 +203,6 @@ impl<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> Point<'a, Ctx, A> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> From<A> for Point<'a, Ctx, A> {
|
||||
fn from(value: A) -> Self {
|
||||
Self::from_mentionable(value)
|
||||
}
|
||||
}
|
||||
|
||||
type TypelessSerialize<'a> = dyn 'a + Fn(&mut dyn Serializer);
|
||||
|
||||
/// See [`Mentionable::points`].
|
||||
pub struct TypelessMentionable<'a, Ctx: 'a + Context> {
|
||||
t_serialize: Box<TypelessSerialize<'a>>,
|
||||
t_factory: TypelessFactory<'a, Ctx>,
|
||||
t_topology: Hash,
|
||||
t_points: Vec<Point<'a, Ctx, TypelessMentionable<'a, Ctx>>>,
|
||||
}
|
||||
|
||||
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>>, &mut Addresses) -> TypelessParsed<'a, Ctx>;
|
||||
|
||||
type TypelessUnexpectedTail<'a> = dyn 'a + Fn(&[u8]) -> TypelessError<'a>;
|
||||
|
||||
/// See [`Mentionable::points`]/[`TypelessMentionable`].
|
||||
pub struct TypelessFactory<'a, Ctx: 'a + Context> {
|
||||
t_deserialize: Rc<TypelessDeserialize<'a, Ctx>>,
|
||||
t_unexpected_tail: Rc<TypelessUnexpectedTail<'a>>,
|
||||
}
|
||||
|
||||
impl<'a, Ctx: 'a + Context> Serializable for TypelessMentionable<'a, Ctx> {
|
||||
fn serialize(&self, serializer: &mut dyn Serializer) {
|
||||
(self.t_serialize)(serializer);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, Ctx: 'a + Context> Mentionable<'a, Ctx> for TypelessMentionable<'a, Ctx> {
|
||||
type Fctr = TypelessFactory<'a, Ctx>;
|
||||
|
||||
fn factory(&self) -> Self::Fctr {
|
||||
self.t_factory.clone()
|
||||
}
|
||||
|
||||
fn topology(&self) -> Hash {
|
||||
self.t_topology
|
||||
}
|
||||
|
||||
fn points(&self, points: &mut Vec<Point<'a, Ctx, TypelessMentionable<'a, Ctx>>>) {
|
||||
points.extend(self.t_points.iter().map(Clone::clone));
|
||||
}
|
||||
|
||||
fn points_vec(&self) -> Vec<Point<'a, Ctx, TypelessMentionable<'a, Ctx>>> {
|
||||
self.t_points.clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, Ctx: 'a + Context> Clone for TypelessFactory<'a, Ctx> {
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
t_deserialize: self.t_deserialize.clone(),
|
||||
t_unexpected_tail: self.t_unexpected_tail.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// See [`Mentionable::points`]/[`TypelessFactory`].
|
||||
#[derive(Debug)]
|
||||
pub struct TypelessError<'a>(Box<dyn 'a + Error>);
|
||||
|
||||
impl<'a> Display for TypelessError<'a> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.write_fmt(format_args!("typeless error: {}", self.0))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Error for TypelessError<'a> {}
|
||||
|
||||
impl<'a, Ctx: 'a + Context> Factory<'a, Ctx> for TypelessFactory<'a, Ctx> {
|
||||
type Mtbl = TypelessMentionable<'a, Ctx>;
|
||||
|
||||
type ParseError = TypelessError<'a>;
|
||||
|
||||
fn deserialize(
|
||||
&self,
|
||||
deserializer: &mut dyn Deserializer,
|
||||
resolver: Rc<dyn Resolver<'a, Ctx>>,
|
||||
addresses: &mut Addresses,
|
||||
) -> ParseResult<'a, Ctx, Self> {
|
||||
match (self.t_deserialize)(deserializer, resolver, addresses) {
|
||||
Ok(mentionable) => Ok(mentionable),
|
||||
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> {
|
||||
pub fn from_typed<A: Mentionable<'a, Ctx>>(mentionable: Rc<A>) -> Self {
|
||||
let factory = TypelessFactory::from_typed(mentionable.factory());
|
||||
let topology = mentionable.topology();
|
||||
let points = mentionable.points_vec();
|
||||
TypelessMentionable {
|
||||
t_serialize: Box::new(move |serializer| mentionable.serialize(serializer)),
|
||||
t_factory: factory,
|
||||
t_topology: topology,
|
||||
t_points: points,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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, addresses| {
|
||||
match factory.deserialize(deserializer, resolver, addresses) {
|
||||
Ok(mentionable) => Ok(TypelessMentionable::from_typed(Rc::new(mentionable))),
|
||||
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))
|
||||
}
|
||||
}
|
||||
|
||||
/// Preferred way to parse [Point]s off of a [Serializer].
|
||||
pub struct Addresses {
|
||||
current: usize,
|
||||
@ -544,3 +362,13 @@ impl<'a> Deserializer for SliceDeserializer<'a> {
|
||||
self.pos
|
||||
}
|
||||
}
|
||||
|
||||
impl Serializer for Vec<u8> {
|
||||
fn write(&mut self, buf: &[u8]) {
|
||||
self.extend(buf);
|
||||
}
|
||||
|
||||
fn tell(&self) -> usize {
|
||||
self.len()
|
||||
}
|
||||
}
|
||||
|
132
src/core/typeless.rs
Normal file
132
src/core/typeless.rs
Normal file
@ -0,0 +1,132 @@
|
||||
//! Typeless. See [`Mentionable::points`].
|
||||
|
||||
use super::*;
|
||||
|
||||
type TypelessSerialize<'a> = dyn 'a + Fn(&mut dyn Serializer);
|
||||
|
||||
/// See [`Mentionable::points`].
|
||||
pub struct TypelessMentionable<'a, Ctx: 'a + Context> {
|
||||
t_serialize: Box<TypelessSerialize<'a>>,
|
||||
t_factory: TypelessFactory<'a, Ctx>,
|
||||
t_topology: Hash,
|
||||
t_points: Vec<Point<'a, Ctx, TypelessMentionable<'a, Ctx>>>,
|
||||
}
|
||||
|
||||
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>>, &mut Addresses) -> TypelessParsed<'a, Ctx>;
|
||||
|
||||
type TypelessUnexpectedTail<'a> = dyn 'a + Fn(&[u8]) -> TypelessError<'a>;
|
||||
|
||||
/// See [`Mentionable::points`]/[`TypelessMentionable`].
|
||||
pub struct TypelessFactory<'a, Ctx: 'a + Context> {
|
||||
t_deserialize: Rc<TypelessDeserialize<'a, Ctx>>,
|
||||
t_unexpected_tail: Rc<TypelessUnexpectedTail<'a>>,
|
||||
}
|
||||
|
||||
impl<'a, Ctx: 'a + Context> Serializable for TypelessMentionable<'a, Ctx> {
|
||||
fn serialize(&self, serializer: &mut dyn Serializer) {
|
||||
(self.t_serialize)(serializer);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, Ctx: 'a + Context> Mentionable<'a, Ctx> for TypelessMentionable<'a, Ctx> {
|
||||
type Fctr = TypelessFactory<'a, Ctx>;
|
||||
|
||||
fn factory(&self) -> Self::Fctr {
|
||||
self.t_factory.clone()
|
||||
}
|
||||
|
||||
fn topology(&self) -> Hash {
|
||||
self.t_topology
|
||||
}
|
||||
|
||||
fn points(&self, points: &mut Vec<Point<'a, Ctx, TypelessMentionable<'a, Ctx>>>) {
|
||||
points.extend(self.t_points.iter().map(Clone::clone));
|
||||
}
|
||||
|
||||
fn points_vec(&self) -> Vec<Point<'a, Ctx, TypelessMentionable<'a, Ctx>>> {
|
||||
self.t_points.clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, Ctx: 'a + Context> Clone for TypelessFactory<'a, Ctx> {
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
t_deserialize: self.t_deserialize.clone(),
|
||||
t_unexpected_tail: self.t_unexpected_tail.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// See [`Mentionable::points`]/[`TypelessFactory`].
|
||||
#[derive(Debug)]
|
||||
pub struct TypelessError<'a>(Box<dyn 'a + Error>);
|
||||
|
||||
impl<'a> Display for TypelessError<'a> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.write_fmt(format_args!("typeless error: {}", self.0))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Error for TypelessError<'a> {}
|
||||
|
||||
impl<'a, Ctx: 'a + Context> Factory<'a, Ctx> for TypelessFactory<'a, Ctx> {
|
||||
type Mtbl = TypelessMentionable<'a, Ctx>;
|
||||
|
||||
type ParseError = TypelessError<'a>;
|
||||
|
||||
fn deserialize(
|
||||
&self,
|
||||
deserializer: &mut dyn Deserializer,
|
||||
resolver: Rc<dyn Resolver<'a, Ctx>>,
|
||||
addresses: &mut Addresses,
|
||||
) -> ParseResult<'a, Ctx, Self> {
|
||||
match (self.t_deserialize)(deserializer, resolver, addresses) {
|
||||
Ok(mentionable) => Ok(mentionable),
|
||||
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> {
|
||||
pub fn from_typed<A: Mentionable<'a, Ctx>>(mentionable: Rc<A>) -> Self {
|
||||
let factory = TypelessFactory::from_typed(mentionable.factory());
|
||||
let topology = mentionable.topology();
|
||||
let points = mentionable.points_vec();
|
||||
TypelessMentionable {
|
||||
t_serialize: Box::new(move |serializer| mentionable.serialize(serializer)),
|
||||
t_factory: factory,
|
||||
t_topology: topology,
|
||||
t_points: points,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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, addresses| {
|
||||
match factory.deserialize(deserializer, resolver, addresses) {
|
||||
Ok(mentionable) => Ok(TypelessMentionable::from_typed(Rc::new(mentionable))),
|
||||
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))
|
||||
}
|
||||
}
|
@ -4,6 +4,7 @@ pub mod atomic;
|
||||
pub mod cast;
|
||||
pub mod collections;
|
||||
pub mod inlining;
|
||||
mod local_origin;
|
||||
pub mod nullable;
|
||||
|
||||
use std::{error::Error, fmt::Display, rc::Rc};
|
||||
|
53
src/std/local_origin.rs
Normal file
53
src/std/local_origin.rs
Normal file
@ -0,0 +1,53 @@
|
||||
use std::rc::Rc;
|
||||
|
||||
use crate::core::*;
|
||||
use crate::func::*;
|
||||
|
||||
impl<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> Point<'a, Ctx, A> {
|
||||
fn prepare_bytes_for_hashing(mentioned: &A) -> Vec<u8> {
|
||||
let mut vec = mentioned.topology().to_vec();
|
||||
mentioned.serialize(&mut vec);
|
||||
vec
|
||||
}
|
||||
|
||||
fn from_fields(point: Hash, origin: Rc<dyn Origin<'a, Ctx, Mtbl = A>>) -> Self {
|
||||
Point { point, origin }
|
||||
}
|
||||
|
||||
fn from_values<O: Origin<'a, Ctx, Mtbl = A>>(point: Hash, origin: O) -> Self {
|
||||
Self::from_fields(point, Rc::new(origin))
|
||||
}
|
||||
|
||||
fn from_mentionable(mentionable: A) -> Self {
|
||||
Self::from_values(
|
||||
Ctx::hash(Self::prepare_bytes_for_hashing(&mentionable).as_slice()),
|
||||
LocalOrigin::from(mentionable),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
struct LocalOrigin<A>(Rc<A>);
|
||||
|
||||
impl<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> Origin<'a, Ctx> for LocalOrigin<A> {
|
||||
type Mtbl = A;
|
||||
|
||||
fn factory(&self) -> A::Fctr {
|
||||
self.0.factory()
|
||||
}
|
||||
|
||||
fn resolve(self: Rc<Self>) -> Resolution<'a, Ctx, Self::Mtbl> {
|
||||
Ctx::T::pure(Ok(self.0.clone()))
|
||||
}
|
||||
}
|
||||
|
||||
impl<A> From<A> for LocalOrigin<A> {
|
||||
fn from(value: A) -> Self {
|
||||
LocalOrigin(value.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> From<A> for Point<'a, Ctx, A> {
|
||||
fn from(value: A) -> Self {
|
||||
Self::from_mentionable(value)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user