//! 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. mod addresses; mod hashing; mod points; mod resolution; mod resolver_origin; mod serialization; mod slice_deserializer; use std::{error::Error, rc::Rc}; use crate::func::*; pub use self::addresses::*; pub use self::hashing::*; pub use self::points::TakesPoints; pub use self::resolution::*; pub use self::serialization::*; pub use self::slice_deserializer::*; /// Basic support for tracing events across the execution. pub trait Diagnostic { /// Specify that the evaluation happens after a specific event. fn after<'a, A>(fa: T::F<'a, A>, event: &'a str) -> T::F<'a, A>; /// Specify that the evaluation happens before a specific event. fn before<'a, A>(fa: T::F<'a, A>, event: &'a str) -> T::F<'a, A>; /// Label the evaluation step as a specific named action. fn wrapped<'a, A>(fa: T::F<'a, A>, event: &'a str) -> T::F<'a, A>; } /// Execution context. pub trait Context { /// Type to provide for [Monad]ic representation of computation, mostly that of resolution ([`Resolution`]). type T: Monad; /// Type to allow improved support for result evaluation. /// This is important for async applications stopping early. type Fallible: MonadFailOver; /// See [`Diagnostic`]. type D: Diagnostic; /// 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; } /// Helper alias for [`WeakFunctor::F`] of [`Context::T`]. pub type Wrapped<'a, Ctx, A> = <::T as WeakFunctor>::F<'a, A>; /// 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(); self.points_typed(&mut vec); Ctx::hash(&vec) } /// References ([Point]s) to other objects. Typed. fn points_typed(&self, points: &mut impl TakesPoints<'a, Ctx>); } /// Shorthand 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 [`crate::std::ctypeless`]. pub trait Factory<'a, Ctx: 'a + Context>: 'a + Send + Sync + Clone { /// 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>, 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; } /// 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>; } /// The main way to represent a reference in ADN. pub struct Point<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> { /// Hash of the referred content. /// Derived both from the serialised value ([`Serializable::serialize`]) /// and its topology ([`Mentionable::topology`]). pub point: Hash, /// [Origin] used in [`Point::resolve`]. 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> { /// See [`Origin::resolve`]. pub fn resolve(&self) -> Resolution<'a, Ctx, A> { self.origin.clone().resolve() } } /// Extension trait for factories. pub trait ExtFactory<'a, Ctx: 'a + Context>: Factory<'a, Ctx> { /// Parse the object from a slice. fn parse_slice( &self, slice: &[u8], resolver: Rc>, ) -> ParseResult<'a, Ctx, Self>; }