diff --git a/src/core.rs b/src/core.rs index dc78c07..9c0f872 100644 --- a/src/core.rs +++ b/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() + } +} diff --git a/src/core/typeless.rs b/src/core/typeless.rs new file mode 100644 index 0000000..298e140 --- /dev/null +++ b/src/core/typeless.rs @@ -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)) + } +} diff --git a/src/std.rs b/src/std.rs index c31ff22..9b2ac52 100644 --- a/src/std.rs +++ b/src/std.rs @@ -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}; diff --git a/src/std/local_origin.rs b/src/std/local_origin.rs new file mode 100644 index 0000000..5063184 --- /dev/null +++ b/src/std/local_origin.rs @@ -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) + } +}