//! Core module for ADN functionality. //! 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 crate::func::*; /// Execution context. pub trait Context { /// Type to provide for [Monad]ic representation of computation, mostly that of resolution ([`Resolution`]). type T: Monad; /// Type to represent resolution errors mainly arising in [`Resolver::resolve`]. type LookupError<'a>: 'a + Error; /// Get [type@Hash] of a slice, mostly for use in [`Point`]. fn hash(s: &[u8]) -> Hash; } /// Failure yielded by [`Origin`]. #[derive(Debug)] pub enum ResolutionError { Lookup(L), Parse(P), } /// See [`ResolutionResult`]. pub type ResolutionFailure<'a, Ctx, A> = ResolutionError< ::LookupError<'a>, <>::Fctr as Factory<'a, Ctx>>::ParseError, >; /// Result yielded by [`Origin`]. pub type ResolutionResult<'a, Ctx, A> = Result, ResolutionFailure<'a, Ctx, A>>; /// Helper alias for [`WeakFunctor::F`] of [`Context::T`]. pub type Wrapped<'a, Ctx, A> = <::T as WeakFunctor>::F<'a, A>; /// Wrapped result returned by [`Origin`]. pub type Resolution<'a, Ctx, A> = Wrapped<'a, Ctx, ResolutionResult<'a, Ctx, A>>; /// Fixed [type@Hash] length. pub const HASH_SIZE: usize = 32; /// Zeroed out array of the same length as [`type@Hash`]. /// Used in [`crate::std::nullable`]. pub const HASH_ZEROS: [u8; HASH_SIZE] = [0; HASH_SIZE]; /// For use in [`Point`]/[`Address`]. pub type Hash = [u8; HASH_SIZE]; /// Serialisation mechanism that is chosen over bytestring concatenation /// both for performance and simplicity. /// /// See [`Serializable`]. pub trait Serializer { /// Writes bytes from a slice. Should advance value of [`Serializer::tell()`] by `buf.len()`. fn write(&mut self, buf: &[u8]); /// Current position of the stream. It's expected to be used by [`crate::std::inlining`] fn tell(&self) -> usize; } impl Serializer for Vec { 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`]. fn serialize(&self, serializer: &mut dyn Serializer); } /// Fundamental trait for ADN objects. pub trait Mentionable<'a, Ctx: 'a + Context>: 'a + Serializable { /// Type of the associated factory. type Fctr: Factory<'a, Ctx, Mtbl = Self>; /// Value of the associated factory. fn factory(&self) -> Self::Fctr; /// See implementation for the definition. /// Hash of all the references' points concatenated, ordered, non-unique. /// Used for walking over object trees to ensure two objects with different references don't collide. fn topology(&self) -> Hash { let mut vec = Vec::new(); for point in self.points() { vec.extend(point.point); } Ctx::hash(&vec) } /// References ([Point]s) to other objects. fn points(&self) -> Vec>>; } /// Short-hand for the type of values returned by [`Resolver::resolve`]. pub type HashResolution<'a, Ctx> = Wrapped< 'a, Ctx, Result<(Vec, Rc>), ::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, address: Address) -> HashResolution<'a, Ctx>; } /// Trait representing a readable stream used for parsing. /// /// See [`Serializer`], [`Factory::deserialize`]. pub trait Deserializer { /// Read at most `n` bytes. fn read_n(&mut self, n: usize) -> &[u8]; /// Read til the end of the stream. fn read_all(&mut self) -> &[u8]; /// See [`Serializer::tell`]. fn tell(&self) -> usize; } /// Short-hand for the type of vaalues returned by [`Factory::deserialize`]. pub type ParseResult<'a, Ctx, F> = Result<>::Mtbl, >::ParseError>; /// Trait representing deserialisation rules for [Mentionable]s. /// Crucial for [`TypelessMentionable`] and therefore [`Mentionable::points`]. pub trait Factory<'a, Ctx: 'a + Context>: Clone + 'a { /// Type of the associated objects. type Mtbl: Mentionable<'a, Ctx, Fctr = Self>; /// Type of an error that [`Factory::deserialize`] can fail with. type ParseError: 'a + Error; /// See [`Deserializer`], [`Resolver`]. fn deserialize( &self, deserializer: &mut dyn Deserializer, resolver: Rc>, ) -> ParseResult<'a, Ctx, Self>; /// Called by finite stream parsers if there's any data left. fn unexpected_tail(&self, tail: &[u8]) -> Self::ParseError; } /// Represents a potentially resolvable [`Mentionable`]. pub trait Origin<'a, Ctx: 'a + Context>: 'a { /// Type of the associated object. type Mtbl: Mentionable<'a, Ctx>; /// Value of the associated factory. fn factory(&self) -> >::Fctr; /// Try resolving the value. fn resolve(self: Rc) -> Resolution<'a, Ctx, Self::Mtbl>; } struct LocalOrigin(Rc); impl<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> Origin<'a, Ctx> for LocalOrigin { type Mtbl = A; fn factory(&self) -> A::Fctr { self.0.factory() } fn resolve(self: Rc) -> Resolution<'a, Ctx, Self::Mtbl> { Ctx::T::pure(Ok(self.0.clone())) } } impl From for LocalOrigin { 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, pub origin: Rc>, } impl<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> Clone for Point<'a, Ctx, A> { fn clone(&self) -> Self { Self { point: self.point, origin: self.origin.clone(), } } } impl<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> Point<'a, Ctx, A> { fn prepare_bytes_for_hashing(mentioned: &A) -> Vec { let mut vec = mentioned.topology().to_vec(); mentioned.serialize(&mut vec); vec } fn from_fields(point: Hash, origin: Rc>) -> Self { Point { point, origin } } fn from_values>(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), ) } } impl<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> From 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>, t_factory: TypelessFactory<'a, Ctx>, t_topology: Hash, t_points: Vec>>, } type TypelessParsed<'a, Ctx> = Result, Box>; type TypelessDeserialize<'a, Ctx> = dyn 'a + Fn(&mut dyn Deserializer, Rc>) -> 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>, t_unexpected_tail: Rc>, } 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) -> Vec>> { 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); 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>, ) -> ParseResult<'a, Ctx, Self> { match (self.t_deserialize)(deserializer, resolver) { 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>(mentionable: Rc) -> Self { let factory = TypelessFactory::from_typed(mentionable.factory()); let topology = mentionable.topology(); let points = mentionable.points(); 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>(factory: F) -> Self { let tail_factory = factory.clone(); TypelessFactory { t_deserialize: Rc::new(move |deserializer, resolver| { match factory.deserialize(deserializer, resolver) { 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(error: E) -> Self { TypelessError(Box::new(error)) } }