radn-rs/src/rcore.rs
2023-06-30 22:12:47 +00:00

150 lines
4.6 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 context;
mod diagnostic;
mod hashing;
mod inctx;
mod inlining;
mod origin;
mod point;
mod points;
mod resolution;
mod resolver_origin;
mod serialization;
mod slice_deserializer;
use std::{error::Error, rc::Rc};
use crate::func::context::*;
use crate::func::*;
pub use self::addresses::{Addresses, InliningAddresses};
pub use self::context::Context;
pub use self::diagnostic::Diagnostic;
pub use self::hashing::{Hash, HASH_SIZE, HASH_ZEROS};
pub use self::inctx::InCtx;
pub use self::inlining::{Inlining, InliningExt};
pub use self::origin::{OFctr, Origin};
pub use self::point::Point;
pub use self::points::TakesPoints;
pub use self::resolution::{
Address, HashResolution, HashResolutionResult, Resolution, ResolutionError, ResolutionFailure,
ResolutionResult, Resolver, ResolverMap,
};
pub use self::serialization::{Deserializer, DeserializerExt, Serializable, Serializer};
pub use self::slice_deserializer::SliceDeserializer;
/// Helper alias for [`WeakFunctor::F`] of [`FunctorContext::T`].
pub type Wrapped<'a, Ctx, A> = WrapC<'a, A, Ctx>;
/// Fundamental trait for ADN objects.
pub trait Mentionable<'a, Ctx: Context<'a>>: '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>);
}
pub type Fctr<'a, Ctx, A> = <A as Mentionable<'a, Ctx>>::Fctr;
/// Shorthand for the type of vaalues returned by [`Factory::deserialize`].
pub type ParseResult<'a, Ctx, F> = Result<Mtbl<'a, Ctx, F>, <F as Factory<'a, Ctx>>::ParseError>;
pub type ParseResultA<'a, Ctx, A> = Result<A, ParseErrorA<'a, Ctx, A>>;
pub struct DeCtxT<'a: 'c, 'c, Ctx: Context<'a>> {
deserializer: &'c mut dyn Deserializer,
resolver: &'c Rc<dyn Resolver<'a, Ctx>>,
addresses: &'c mut Addresses,
}
pub trait DeCtx<'a, Ctx: Context<'a>> {
fn deserializer(&mut self) -> &mut dyn Deserializer;
fn tell(&self) -> usize;
fn next_address(&mut self) -> Result<Address, &[u8]>;
fn resolver(&self) -> Rc<dyn Resolver<'a, Ctx>>;
fn adr(
&mut self,
) -> (
&mut Addresses,
&mut dyn Deserializer,
&Rc<dyn Resolver<'a, Ctx>>,
);
}
impl<'a: 'c, 'c, Ctx: Context<'a>> DeCtx<'a, Ctx> for DeCtxT<'a, 'c, Ctx> {
fn deserializer(&mut self) -> &mut dyn Deserializer {
self.deserializer
}
fn tell(&self) -> usize {
self.deserializer.tell()
}
fn next_address(&mut self) -> Result<Address, &[u8]> {
self.addresses.next(self.deserializer)
}
fn resolver(&self) -> Rc<dyn Resolver<'a, Ctx>> {
self.resolver.clone()
}
fn adr(
&mut self,
) -> (
&mut Addresses,
&mut dyn Deserializer,
&Rc<dyn Resolver<'a, Ctx>>,
) {
(&mut self.addresses, self.deserializer, self.resolver)
}
}
/// Trait representing deserialisation rules for [Mentionable]s.
/// Crucial for [`crate::rstd::typeless`].
pub trait Factory<'a, Ctx: Context<'a>>: '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, dectx: &mut dyn DeCtx<'a, Ctx>) -> ParseResult<'a, Ctx, Self>;
/// Called by finite stream parsers if there's any data left.
fn extend(&self, mentionable: Self::Mtbl, tail: &[u8]) -> ParseResult<'a, Ctx, Self>;
}
pub type Mtbl<'a, Ctx, F> = <F as Factory<'a, Ctx>>::Mtbl;
pub type ParseError<'a, Ctx, F> = <F as Factory<'a, Ctx>>::ParseError;
pub type ParseErrorA<'a, Ctx, A> = ParseError<'a, Ctx, Fctr<'a, Ctx, A>>;
/// Extension trait for factories.
pub trait FactoryExt<'a, Ctx: Context<'a>>: 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>;
}