core docs

This commit is contained in:
AF 2023-04-21 22:22:28 +00:00
parent a5fef129fe
commit 4ababb524c
2 changed files with 68 additions and 5 deletions

View File

@ -1,20 +1,30 @@
//! 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 std::{error::Error, fmt::Display, rc::Rc};
use crate::func::*; use crate::func::*;
/// Execution context.
pub trait Context { pub trait Context {
/// Type to provide for [Monad]ic representation of computation, mostly that of resolution ([`Resolution`]).
type T: Monad; type T: Monad;
/// Type to represent resolution errors mainly arising in [`Resolver::resolve`].
type LookupError: Error; type LookupError: Error;
/// Get [type@Hash] of a slice, mostly for use in [`Point`].
fn hash(s: &[u8]) -> Hash; fn hash(s: &[u8]) -> Hash;
} }
/// Failure yielded by [`Origin`].
pub enum ResolutionError<L, P> { pub enum ResolutionError<L, P> {
Lookup(L), Lookup(L),
Parse(P), Parse(P),
} }
/// Result yielded by [`Origin`].
pub type ResolutionResult<'a, Ctx, A> = Result< pub type ResolutionResult<'a, Ctx, A> = Result<
Rc<A>, Rc<A>,
ResolutionError< ResolutionError<
@ -23,18 +33,30 @@ pub type ResolutionResult<'a, Ctx, A> = Result<
>, >,
>; >;
/// Helper alias for [`WeakFunctor::F`] of [`Context::T`].
pub type Wrapped<'a, Ctx, A> = <<Ctx as Context>::T as WeakFunctor>::F<'a, A>; pub type Wrapped<'a, Ctx, A> = <<Ctx as Context>::T as WeakFunctor>::F<'a, A>;
/// Wrapped result returned by [`Origin`].
pub type Resolution<'a, Ctx, A> = Wrapped<'a, Ctx, ResolutionResult<'a, Ctx, A>>; pub type Resolution<'a, Ctx, A> = Wrapped<'a, Ctx, ResolutionResult<'a, Ctx, A>>;
/// Fixed [type@Hash] length.
pub const HASH_SIZE: usize = 32; 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]; pub const HASH_ZEROS: [u8; HASH_SIZE] = [0; HASH_SIZE];
/// For use in [`Point`]/[`Address`].
pub type Hash = [u8; HASH_SIZE]; pub type Hash = [u8; HASH_SIZE];
/// Serialisation mechanism that is chosen over bytestring concatenation
/// both for performance and simplicity.
///
/// See [`Serializable`].
pub trait Serializer { pub trait Serializer {
/// Writes bytes from a slice. Should advance value of [`Serializer::tell()`] by `buf.len()`.
fn write(&mut self, buf: &[u8]); 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; fn tell(&self) -> usize;
} }
@ -48,14 +70,22 @@ impl Serializer for Vec<u8> {
} }
} }
/// See [`Serializer`].
pub trait Serializable { pub trait Serializable {
/// Expected to use [`Serializer::write`].
fn serialize(&self, serializer: &mut dyn Serializer); fn serialize(&self, serializer: &mut dyn Serializer);
} }
/// Fundamental trait for ADN objects.
pub trait Mentionable<'a, Ctx: 'a + Context>: 'a + Serializable { pub trait Mentionable<'a, Ctx: 'a + Context>: 'a + Serializable {
/// Type of the associated factory.
type Fctr: Factory<'a, Ctx, Mtbl = Self>; type Fctr: Factory<'a, Ctx, Mtbl = Self>;
/// Value of the associated factory.
fn factory(&self) -> Self::Fctr; 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 { fn topology(&self) -> Hash {
let mut vec = Vec::new(); let mut vec = Vec::new();
for point in self.points() { for point in self.points() {
@ -63,47 +93,70 @@ pub trait Mentionable<'a, Ctx: 'a + Context>: 'a + Serializable {
} }
Ctx::hash(&vec) Ctx::hash(&vec)
} }
/// References ([Point]s) to other objects.
fn points(&self) -> Vec<Point<'a, Ctx, TypelessMentionable<'a, Ctx>>>; fn points(&self) -> Vec<Point<'a, Ctx, TypelessMentionable<'a, Ctx>>>;
} }
/// Short-hand for the type of values returned by [`Resolver::resolve`].
pub type HashResolution<'a, Ctx> = pub type HashResolution<'a, Ctx> =
Wrapped<'a, Ctx, Result<(Vec<u8>, Rc<dyn Resolver<'a, Ctx>>), <Ctx as Context>::LookupError>>; Wrapped<'a, Ctx, Result<(Vec<u8>, Rc<dyn Resolver<'a, Ctx>>), <Ctx as Context>::LookupError>>;
/// Value accepted by [`Resolver::resolve`]. Includes index to make it order-sensitive.
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
pub struct Address { pub struct Address {
pub point: Hash, pub point: Hash,
/// Index of the point in the [`Mentionable::points()`].
pub index: usize, pub index: usize,
} }
/// Trait representing the "rainbow table" behaviour.
pub trait Resolver<'a, Ctx: 'a + Context>: 'a { 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<Self>, address: Address) -> HashResolution<'a, Ctx>; fn resolve(self: Rc<Self>, address: Address) -> HashResolution<'a, Ctx>;
} }
/// Trait representing a readable stream used for parsing.
///
/// See [`Serializer`], [`Factory::deserialize`].
pub trait Deserializer { pub trait Deserializer {
/// Read at most `n` bytes.
fn read_n(&mut self, n: usize) -> &[u8]; fn read_n(&mut self, n: usize) -> &[u8];
/// Read til the end of the stream.
fn read_all(&mut self) -> &[u8]; fn read_all(&mut self) -> &[u8];
/// See [`Serializer::tell`].
fn tell(&self) -> usize; fn tell(&self) -> usize;
} }
/// Short-hand for the type of vaalues returned by [`Factory::deserialize`].
pub type ParseResult<'a, Ctx, F> = pub type ParseResult<'a, Ctx, F> =
Result<<F as Factory<'a, Ctx>>::Mtbl, <F as Factory<'a, Ctx>>::ParseError>; 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 { pub trait Factory<'a, Ctx: 'a + Context>: Clone + 'a {
/// Type of the associated objects.
type Mtbl: Mentionable<'a, Ctx, Fctr = Self>; type Mtbl: Mentionable<'a, Ctx, Fctr = Self>;
/// Type of an error that [`Factory::deserialize`] can fail with.
type ParseError: 'a + Error; type ParseError: 'a + Error;
/// See [`Deserializer`], [`Resolver`].
fn deserialize( fn deserialize(
&self, &self,
deserializer: &mut dyn Deserializer, deserializer: &mut dyn Deserializer,
resolver: Rc<dyn Resolver<'a, Ctx>>, resolver: Rc<dyn Resolver<'a, Ctx>>,
) -> ParseResult<'a, Ctx, Self>; ) -> ParseResult<'a, Ctx, Self>;
/// Called by finite stream parsers if there's any data left.
fn unexpected_tail(&self, tail: &[u8]) -> Self::ParseError; fn unexpected_tail(&self, tail: &[u8]) -> Self::ParseError;
} }
/// Represents a potentially resolvable [`Mentionable`].
pub trait Origin<'a, Ctx: 'a + Context>: 'a { pub trait Origin<'a, Ctx: 'a + Context>: 'a {
/// Type of the associated object.
type Mtbl: Mentionable<'a, Ctx>; type Mtbl: Mentionable<'a, Ctx>;
/// Value of the associated factory.
fn factory(&self) -> <Self::Mtbl as Mentionable<'a, Ctx>>::Fctr; fn factory(&self) -> <Self::Mtbl as Mentionable<'a, Ctx>>::Fctr;
/// Try resolving the value.
fn resolve(self: Rc<Self>) -> Resolution<'a, Ctx, Self::Mtbl>; fn resolve(self: Rc<Self>) -> Resolution<'a, Ctx, Self::Mtbl>;
} }
@ -127,6 +180,7 @@ impl<A> From<A> for LocalOrigin<A> {
} }
} }
/// The main way to represent a reference in ADN.
pub struct Point<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> { pub struct Point<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> {
pub point: Hash, pub point: Hash,
pub origin: Rc<dyn Origin<'a, Ctx, Mtbl = A>>, pub origin: Rc<dyn Origin<'a, Ctx, Mtbl = A>>,
@ -156,22 +210,28 @@ impl<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> Point<'a, Ctx, A> {
Self::from_fields(point, Rc::new(origin)) Self::from_fields(point, Rc::new(origin))
} }
/// See [`Origin::resolve`].
pub fn resolve(&self) -> Resolution<'a, Ctx, A> { pub fn resolve(&self) -> Resolution<'a, Ctx, A> {
self.origin.clone().resolve() 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<A> for 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 { fn from(value: A) -> Self {
Self::from_values( Self::from_mentionable(value)
Ctx::hash(Self::prepare_bytes_for_hashing(&value).as_slice()),
LocalOrigin::from(value),
)
} }
} }
type TypelessSerialize<'a> = dyn 'a + Fn(&mut dyn Serializer); type TypelessSerialize<'a> = dyn 'a + Fn(&mut dyn Serializer);
/// See [`Mentionable::points`].
pub struct TypelessMentionable<'a, Ctx: 'a + Context> { pub struct TypelessMentionable<'a, Ctx: 'a + Context> {
t_serialize: Box<TypelessSerialize<'a>>, t_serialize: Box<TypelessSerialize<'a>>,
t_factory: TypelessFactory<'a, Ctx>, t_factory: TypelessFactory<'a, Ctx>,
@ -186,6 +246,7 @@ type TypelessDeserialize<'a, Ctx> =
type TypelessUnexpectedTail<'a> = dyn 'a + Fn(&[u8]) -> TypelessError<'a>; type TypelessUnexpectedTail<'a> = dyn 'a + Fn(&[u8]) -> TypelessError<'a>;
/// See [`Mentionable::points`]/[`TypelessMentionable`].
pub struct TypelessFactory<'a, Ctx: 'a + Context> { pub struct TypelessFactory<'a, Ctx: 'a + Context> {
t_deserialize: Rc<TypelessDeserialize<'a, Ctx>>, t_deserialize: Rc<TypelessDeserialize<'a, Ctx>>,
t_unexpected_tail: Rc<TypelessUnexpectedTail<'a>>, t_unexpected_tail: Rc<TypelessUnexpectedTail<'a>>,
@ -222,6 +283,7 @@ impl<'a, Ctx: 'a + Context> Clone for TypelessFactory<'a, Ctx> {
} }
} }
/// See [`Mentionable::points`]/[`TypelessFactory`].
#[derive(Debug)] #[derive(Debug)]
pub struct TypelessError<'a>(Box<dyn 'a + Error>); pub struct TypelessError<'a>(Box<dyn 'a + Error>);

View File

@ -84,6 +84,7 @@ impl<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> Origin<'a, Ctx> for Wrapped
} }
impl<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> Point<'a, Ctx, A> { impl<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> Point<'a, Ctx, A> {
/// Typeless version of the point. Useful for [Mentionable::points] implementaion.
pub fn typeless(&self) -> Point<'a, Ctx, TypelessMentionable<'a, Ctx>> { pub fn typeless(&self) -> Point<'a, Ctx, TypelessMentionable<'a, Ctx>> {
Point { Point {
point: self.point, point: self.point,