radn-rs/src/core.rs
2023-03-26 11:59:50 +00:00

105 lines
2.7 KiB
Rust

use std::{error::Error, rc::Rc};
use crate::func::*;
pub trait Context {
type T: Monad;
fn hash(s: &[u8]) -> Hash;
}
type Hash = [u8; 32];
pub trait Serializer {
fn write(&mut self, buf: &[u8]);
}
impl<F: FnMut(&[u8])> Serializer for F {
fn write(&mut self, buf: &[u8]) {
self(buf);
}
}
pub trait Mentionable<Ctx: Context> {
type Fctr: Factory<Ctx, Mtbl = Self>;
fn serialize<F: Serializer>(&self, serializer: F);
fn factory(&self) -> Self::Fctr;
fn topology(&self) -> Hash;
}
pub trait Deserializer {
fn read_n_const<const N: usize>(&mut self) -> Result<[u8; N], &[u8]>;
fn read_n(&mut self, n: usize) -> &[u8];
fn read_all(&mut self, n: usize) -> &[u8];
}
pub trait Factory<Ctx: Context>: Clone {
type Mtbl: Mentionable<Ctx, Fctr = Self>;
type ParseError: Error;
fn deserialize<F: Deserializer>(&self, deserializer: F)
-> Result<Self::Mtbl, Self::ParseError>;
}
pub trait Origin<'a, Ctx: Context>: 'a {
type Mtbl: Mentionable<Ctx>;
fn factory(&self) -> <Self::Mtbl as Mentionable<Ctx>>::Fctr;
fn resolve(&self) -> <<Ctx as Context>::T as WeakFunctor>::F<'a, Rc<Self::Mtbl>>;
}
struct LocalOrigin<A>(Rc<A>);
impl<'a, Ctx: 'a + Context, A: 'a + Mentionable<Ctx>> Origin<'a, Ctx> for LocalOrigin<A> {
type Mtbl = A;
fn factory(&self) -> <Self::Mtbl as Mentionable<Ctx>>::Fctr {
self.0.factory()
}
fn resolve(&self) -> <<Ctx as Context>::T as WeakFunctor>::F<'a, Rc<Self::Mtbl>> {
<Ctx::T as Applicative>::pure(self.0.clone())
}
}
impl<A> From<A> for LocalOrigin<A> {
fn from(value: A) -> Self {
LocalOrigin(value.into())
}
}
#[derive(Clone)]
pub struct Point<'a, Ctx: Context, A: Mentionable<Ctx>> {
pub point: Hash,
pub origin: Rc<dyn Origin<'a, Ctx, Mtbl = A>>,
}
impl<'a, Ctx: 'a + Context, A: 'a + Mentionable<Ctx>> Point<'a, Ctx, A> {
fn prepare_bytes_for_hashing(mentioned: &A) -> Vec<u8> {
let mut vec = mentioned.topology().to_vec();
mentioned.serialize(|x: &[u8]| vec.extend(x.iter()));
vec
}
fn from_fields(point: Hash, origin: Rc<dyn Origin<'a, Ctx, Mtbl = A>>) -> Self {
Point { point, origin }
}
fn from_values<O: Origin<'a, Ctx, Mtbl = A>>(point: Hash, origin: O) -> Self {
Self::from_fields(point, Rc::new(origin))
}
pub fn resolve(&self) -> <<Ctx as Context>::T as WeakFunctor>::F<'a, Rc<A>> {
self.origin.resolve()
}
}
impl<'a, Ctx: 'a + Context, A: 'a + Mentionable<Ctx>> From<A> for Point<'a, Ctx, A> {
fn from(value: A) -> Self {
Self::from_values(
Ctx::hash(Self::prepare_bytes_for_hashing(&value).as_slice()),
LocalOrigin::from(value),
)
}
}