127 lines
4.3 KiB
Rust
127 lines
4.3 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 hashing;
|
|
mod resolution;
|
|
mod serialization;
|
|
mod slice_deserializer;
|
|
mod typeless;
|
|
|
|
pub use hashing::*;
|
|
pub use resolution::*;
|
|
pub use serialization::*;
|
|
pub use slice_deserializer::*;
|
|
pub use typeless::*;
|
|
|
|
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;
|
|
}
|
|
|
|
/// 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();
|
|
for point in self.points_vec() {
|
|
vec.extend(point.point);
|
|
}
|
|
Ctx::hash(&vec)
|
|
}
|
|
/// References ([Point]s) to other objects.
|
|
fn points(&self, points: &mut Vec<Point<'a, Ctx, TypelessMentionable<'a, Ctx>>>);
|
|
/// [Vec] of [Point]s as used by [`Mentionable::topology`].
|
|
fn points_vec(&self) -> Vec<Point<'a, Ctx, TypelessMentionable<'a, Ctx>>> {
|
|
let mut points = Vec::new();
|
|
self.points(&mut points);
|
|
points
|
|
}
|
|
}
|
|
|
|
/// Short-hand 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 [`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<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>> {
|
|
pub point: Hash,
|
|
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>;
|
|
}
|