240 lines
6.8 KiB
Rust
240 lines
6.8 KiB
Rust
//! Previously part of [`crate::rcore`].
|
|
|
|
use super::{cast::CastError, wrapped_origin::*, *};
|
|
|
|
type TypelessSerialize<'a> = dyn 'a + Fn(&mut dyn Serializer);
|
|
|
|
/// See [`Point::typeless`].
|
|
pub struct TypelessMentionable<'a, Ctx: Context<'a>> {
|
|
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: Context<'a>>: 'a + Send + Sync {
|
|
fn clone_box(&self) -> TdeBox<'a, Ctx>;
|
|
|
|
fn de<'c>(&self, demoted: Demoted<'a, 'c, Ctx>) -> TypelessParsed<'a, Ctx>
|
|
where
|
|
'a: 'c;
|
|
}
|
|
|
|
type TdeBox<'a, Ctx> = Box<dyn Tde<'a, Ctx>>;
|
|
|
|
trait Tut<'a, Ctx: Context<'a>>: 'a + Send + Sync {
|
|
fn clone_box(&self) -> TutBox<'a, Ctx>;
|
|
|
|
fn xt(
|
|
&self,
|
|
mentionable: TypelessMentionable<'a, Ctx>,
|
|
tail: &[u8],
|
|
) -> Result<TypelessMentionable<'a, Ctx>, TypelessError<'a>>;
|
|
}
|
|
|
|
type TutBox<'a, Ctx> = Box<dyn Tut<'a, Ctx>>;
|
|
|
|
/// See [`Point::typeless`]/[`TypelessMentionable`].
|
|
pub struct TypelessFactory<'a, Ctx: Context<'a>> {
|
|
t_deserialize: TdeBox<'a, Ctx>,
|
|
t_extend: TutBox<'a, Ctx>,
|
|
}
|
|
|
|
impl<'a, Ctx: Context<'a>> Serializable for TypelessMentionable<'a, Ctx> {
|
|
fn serialize(&self, serializer: &mut dyn Serializer) {
|
|
(self.t_serialize)(serializer);
|
|
}
|
|
}
|
|
|
|
impl<'a, Ctx: Context<'a>> MentionableBase<'a, Ctx> for TypelessMentionable<'a, Ctx> {
|
|
type Fctr = TypelessFactory<'a, Ctx>;
|
|
|
|
fn factory(&self) -> Self::Fctr {
|
|
self.t_factory.clone()
|
|
}
|
|
}
|
|
|
|
impl<'a, Ctx: Context<'a>> MentionableTop<'a, Ctx> for TypelessMentionable<'a, Ctx> {
|
|
fn topology(&self) -> Hash {
|
|
self.t_topology
|
|
}
|
|
|
|
fn points_typed(&self, points: &mut impl PointsVisitor<'a, Ctx>) {
|
|
for point in self.t_points.iter() {
|
|
points.visit(point)
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<'a, Ctx: Context<'a>> Clone for TypelessFactory<'a, Ctx> {
|
|
fn clone(&self) -> Self {
|
|
Self {
|
|
t_deserialize: self.t_deserialize.clone_box(),
|
|
t_extend: self.t_extend.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 {
|
|
write!(f, "typeless error: {}", self.0)
|
|
}
|
|
}
|
|
|
|
impl<'a> Error for TypelessError<'a> {}
|
|
|
|
impl<'a, Ctx: Context<'a>> FactoryBase<'a, Ctx> for TypelessFactory<'a, Ctx> {
|
|
type Mtbl = TypelessMentionable<'a, Ctx>;
|
|
|
|
type ParseError = TypelessError<'a>;
|
|
}
|
|
|
|
impl<'a, Ctx: Context<'a>> ParseMode for TypelessFactory<'a, Ctx> {
|
|
type Mode = RegularMode;
|
|
}
|
|
|
|
impl<'a, Ctx: Context<'a>> RegularFactory<'a, Ctx> for TypelessFactory<'a, Ctx> {
|
|
fn rdeserialize(&self, inctx: impl InCtx<'a, Ctx>) -> ParseResult<'a, Ctx, Self> {
|
|
self.t_deserialize.de(inctx.demote()).map_err(TypelessError)
|
|
}
|
|
|
|
fn rextend(&self, mentionable: Self::Mtbl, tail: &[u8]) -> ParseResult<'a, Ctx, Self> {
|
|
self.t_extend.xt(mentionable, tail)
|
|
}
|
|
}
|
|
|
|
impl<'a, Ctx: Context<'a>> TypelessMentionable<'a, Ctx>
|
|
where
|
|
Ctx::LookupError: From<CastError<'a>>,
|
|
{
|
|
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: Context<'a>, F: Factory<'a, Ctx>> Tde<'a, Ctx> for F
|
|
where
|
|
Ctx::LookupError: From<CastError<'a>>,
|
|
{
|
|
fn clone_box(&self) -> TdeBox<'a, Ctx> {
|
|
Box::new(self.clone())
|
|
}
|
|
|
|
fn de<'c>(&self, demoted: Demoted<'a, 'c, Ctx>) -> TypelessParsed<'a, Ctx>
|
|
where
|
|
'a: 'c,
|
|
{
|
|
self.deserialize(demoted)
|
|
.map_err(|e| Box::new(e) as _)
|
|
.map(Rc::new)
|
|
.map(TypelessMentionable::from_typed)
|
|
}
|
|
}
|
|
|
|
impl<'a, Ctx: Context<'a>, F: Factory<'a, Ctx>> Tut<'a, Ctx> for F
|
|
where
|
|
Ctx::LookupError: From<CastError<'a>>,
|
|
{
|
|
fn clone_box(&self) -> TutBox<'a, Ctx> {
|
|
Box::new(self.clone())
|
|
}
|
|
|
|
fn xt(
|
|
&self,
|
|
mentionable: TypelessMentionable<'a, Ctx>,
|
|
tail: &[u8],
|
|
) -> Result<TypelessMentionable<'a, Ctx>, TypelessError<'a>> {
|
|
self.extend(
|
|
match mentionable.cast(self.clone()) {
|
|
Ok(m) => m,
|
|
Err(e) => return Err(TypelessError::from_typed(e)),
|
|
},
|
|
tail,
|
|
)
|
|
.map_err(TypelessError::from_typed)
|
|
.map(Rc::new)
|
|
.map(TypelessMentionable::from_typed)
|
|
}
|
|
}
|
|
|
|
impl<'a, Ctx: Context<'a>> TypelessFactory<'a, Ctx>
|
|
where
|
|
Ctx::LookupError: From<CastError<'a>>,
|
|
{
|
|
pub fn from_typed<F: Factory<'a, Ctx>>(factory: F) -> Self {
|
|
TypelessFactory {
|
|
t_deserialize: Box::new(factory.clone()),
|
|
t_extend: Box::new(factory),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<'a> TypelessError<'a> {
|
|
pub fn from_typed<E: 'a + Error>(error: E) -> Self {
|
|
TypelessError(Box::new(error))
|
|
}
|
|
}
|
|
|
|
impl<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx>> Point<'a, Ctx, A>
|
|
where
|
|
Ctx::LookupError: From<CastError<'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: Context<'a>>: 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 [`MentionableTop::topology`].
|
|
fn points_vec(&self) -> Vec<Point<'a, Ctx, TypelessMentionable<'a, Ctx>>>;
|
|
}
|
|
|
|
impl<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx>> MentionableExt<'a, Ctx> for A
|
|
where
|
|
Ctx::LookupError: From<CastError<'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: Context<'a>> PointsVisitor<'a, Ctx>
|
|
for Vec<Point<'a, Ctx, TypelessMentionable<'a, Ctx>>>
|
|
where
|
|
Ctx::LookupError: From<CastError<'a>>,
|
|
{
|
|
fn visit<A: Mentionable<'a, Ctx>>(&mut self, point: &Point<'a, Ctx, A>) {
|
|
self.push(point.typeless());
|
|
}
|
|
}
|