radn-rs/src/core.rs

143 lines
5.0 KiB
Rust

//! 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<T: Monad> {
/// 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<Self::T>;
/// See [`Diagnostic`].
type D: Diagnostic<Self::T>;
/// 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> = <<Ctx as Context>::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<<F as Factory<'a, Ctx>>::Mtbl, <F as Factory<'a, Ctx>>::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<dyn Resolver<'a, Ctx>>,
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) -> <Self::Mtbl as Mentionable<'a, Ctx>>::Fctr;
/// Try resolving the value.
fn resolve(self: Rc<Self>) -> 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<dyn Origin<'a, Ctx, Mtbl = A>>,
}
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<dyn Resolver<'a, Ctx>>,
) -> ParseResult<'a, Ctx, Self>;
}