radn-rs/src/rstd/typeless.rs

211 lines
6.3 KiB
Rust

//! Previously part of [`crate::rcore`].
use super::{wrapped_origin::*, *};
type TypelessSerialize<'a> = dyn 'a + Fn(&mut dyn Serializer);
/// See [`Point::typeless`].
pub struct TypelessMentionable<'a, Ctx: 'a + Context> {
t_serialize: Box<TypelessSerialize<'a>>,
t_factory: TypelessFactory<'a, Ctx>,
t_topology: Hash,
t_points: Vec<Point<'a, Ctx, TypelessMentionable<'a, Ctx>>>,
}
type TypelessParsed<'a, Ctx> = Result<TypelessMentionable<'a, Ctx>, Box<dyn 'a + Error>>;
trait Tde<'a, Ctx: 'a + Context>: 'a + Send + Sync {
fn clone_box(&self) -> TdeBox<'a, Ctx>;
fn de(
&self,
deserializer: &mut dyn Deserializer,
resolver: Rc<dyn Resolver<'a, Ctx>>,
addresses: &mut Addresses,
) -> TypelessParsed<'a, Ctx>;
}
type TdeBox<'a, Ctx> = Box<dyn Tde<'a, Ctx>>;
trait Tut<'a, Ctx: 'a + Context>: 'a + Send + Sync {
fn clone_box(&self) -> TutBox<'a, Ctx>;
fn ut(&self, tail: &[u8]) -> TypelessError<'a>;
}
type TutBox<'a, Ctx> = Box<dyn Tut<'a, Ctx>>;
/// See [`Point::typeless`]/[`TypelessMentionable`].
pub struct TypelessFactory<'a, Ctx: 'a + Context> {
t_deserialize: TdeBox<'a, Ctx>,
t_unexpected_tail: TutBox<'a, Ctx>,
}
impl<'a, Ctx: 'a + Context> Serializable for TypelessMentionable<'a, Ctx> {
fn serialize(&self, serializer: &mut dyn Serializer) {
(self.t_serialize)(serializer);
}
}
impl<'a, Ctx: 'a + Context> Mentionable<'a, Ctx> for TypelessMentionable<'a, Ctx> {
type Fctr = TypelessFactory<'a, Ctx>;
fn factory(&self) -> Self::Fctr {
self.t_factory.clone()
}
fn topology(&self) -> Hash {
self.t_topology
}
fn points_typed(&self, points: &mut impl TakesPoints<'a, Ctx>) {
for point in self.t_points.iter() {
points.take(point)
}
}
}
impl<'a, Ctx: 'a + Context> Clone for TypelessFactory<'a, Ctx> {
fn clone(&self) -> Self {
Self {
t_deserialize: self.t_deserialize.clone_box(),
t_unexpected_tail: self.t_unexpected_tail.clone_box(),
}
}
}
/// See [`Point::typeless`]/[`TypelessFactory`].
#[derive(Debug)]
pub struct TypelessError<'a>(Box<dyn 'a + Error>);
impl<'a> Display for TypelessError<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_fmt(format_args!("typeless error: {}", self.0))
}
}
impl<'a> Error for TypelessError<'a> {}
impl<'a, Ctx: 'a + Context> Factory<'a, Ctx> for TypelessFactory<'a, Ctx> {
type Mtbl = TypelessMentionable<'a, Ctx>;
type ParseError = TypelessError<'a>;
fn deserialize(
&self,
deserializer: &mut dyn Deserializer,
resolver: Rc<dyn Resolver<'a, Ctx>>,
addresses: &mut Addresses,
) -> ParseResult<'a, Ctx, Self> {
match self.t_deserialize.de(deserializer, resolver, addresses) {
Ok(mentionable) => Ok(mentionable),
Err(error) => Err(TypelessError(error)),
}
}
fn unexpected_tail(&self, tail: &[u8]) -> Self::ParseError {
self.t_unexpected_tail.ut(tail)
}
}
impl<'a, Ctx: 'a + Context> TypelessMentionable<'a, Ctx> {
pub fn from_typed<A: Mentionable<'a, Ctx>>(mentionable: Rc<A>) -> Self {
let factory = TypelessFactory::from_typed(mentionable.factory());
let topology = mentionable.topology();
let points = mentionable.points_vec();
TypelessMentionable {
t_serialize: Box::new(move |serializer| mentionable.serialize(serializer)),
t_factory: factory,
t_topology: topology,
t_points: points,
}
}
}
impl<'a, Ctx: 'a + Context, F: Factory<'a, Ctx>> Tde<'a, Ctx> for F {
fn clone_box(&self) -> TdeBox<'a, Ctx> {
Box::new(self.clone())
}
fn de(
&self,
deserializer: &mut dyn Deserializer,
resolver: Rc<dyn Resolver<'a, Ctx>>,
addresses: &mut Addresses,
) -> TypelessParsed<'a, Ctx> {
match self.deserialize(deserializer, resolver, addresses) {
Ok(mentionable) => Ok(TypelessMentionable::from_typed(Rc::new(mentionable))),
Err(error) => {
let boxed: Box<dyn 'a + Error> = Box::new(error);
Err(boxed)
}
}
}
}
impl<'a, Ctx: 'a + Context, F: Factory<'a, Ctx>> Tut<'a, Ctx> for F {
fn clone_box(&self) -> TutBox<'a, Ctx> {
Box::new(self.clone())
}
fn ut(&self, tail: &[u8]) -> TypelessError<'a> {
TypelessError::from_typed(self.unexpected_tail(tail))
}
}
impl<'a, Ctx: 'a + Context> TypelessFactory<'a, Ctx> {
pub fn from_typed<F: Factory<'a, Ctx>>(factory: F) -> Self {
TypelessFactory {
t_deserialize: Box::new(factory.clone()),
t_unexpected_tail: Box::new(factory),
}
}
}
impl<'a> TypelessError<'a> {
pub fn from_typed<E: 'a + Error>(error: E) -> Self {
TypelessError(Box::new(error))
}
}
impl<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> Point<'a, Ctx, A> {
/// Typeless version of the point.
pub fn typeless(&self) -> Point<'a, Ctx, TypelessMentionable<'a, Ctx>> {
Point {
point: self.point,
origin: self.origin.clone().map(
TypelessMentionable::from_typed,
TypelessError::from_typed,
TypelessFactory::from_typed,
),
}
}
}
pub trait MentionableExt<'a, Ctx: 'a + Context>: Mentionable<'a, Ctx> {
/// References ([Point]s) to other objects. Typeless.
fn points_typeless(&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>>>;
}
impl<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> MentionableExt<'a, Ctx> for A {
fn points_typeless(&self, points: &mut Vec<Point<'a, Ctx, TypelessMentionable<'a, Ctx>>>) {
self.points_typed(points)
}
fn points_vec(&self) -> Vec<Point<'a, Ctx, TypelessMentionable<'a, Ctx>>> {
let mut points = Vec::new();
self.points_typeless(&mut points);
points
}
}
impl<'a, Ctx: 'a + Context> TakesPoints<'a, Ctx>
for Vec<Point<'a, Ctx, TypelessMentionable<'a, Ctx>>>
{
fn take<A: Mentionable<'a, Ctx>>(&mut self, point: &Point<'a, Ctx, A>) {
self.push(point.typeless());
}
}