diff --git a/src/rcore/origin.rs b/src/rcore/origin.rs index 7255148..831323a 100644 --- a/src/rcore/origin.rs +++ b/src/rcore/origin.rs @@ -8,6 +8,7 @@ pub trait Origin<'a, Ctx: Context<'a>>: 'a { fn factory(&self) -> OFctr<'a, Ctx, Self>; /// Try resolving the value. fn resolve(self: Rc) -> Resolution<'a, Ctx, Self::Mtbl>; + fn resolve_bytes(self: Rc) -> HashResolution<'a, Ctx>; } pub type OFctr<'a, Ctx, O> = Fctr<'a, Ctx, >::Mtbl>; diff --git a/src/rcore/resolver_origin.rs b/src/rcore/resolver_origin.rs index 4e25650..01460c6 100644 --- a/src/rcore/resolver_origin.rs +++ b/src/rcore/resolver_origin.rs @@ -50,4 +50,8 @@ impl<'a, Ctx: Context<'a>, F: Factory<'a, Ctx>> Origin<'a, Ctx> for ResolverOrig fn resolve(self: Rc) -> Resolution<'a, Ctx, Self::Mtbl> { _resolve_origin(self) } + + fn resolve_bytes(self: Rc) -> HashResolution<'a, Ctx> { + self.r_resolver.clone().resolve(self.r_address) + } } diff --git a/src/rstd.rs b/src/rstd.rs index 7df03c2..5a07f0a 100644 --- a/src/rstd.rs +++ b/src/rstd.rs @@ -8,6 +8,7 @@ pub mod inlining; mod local_origin; pub mod nullable; pub mod point; +pub mod singular; pub mod tracing; pub mod typeless; mod wrapped_origin; diff --git a/src/rstd/cast.rs b/src/rstd/cast.rs index cbfd72b..0abae83 100644 --- a/src/rstd/cast.rs +++ b/src/rstd/cast.rs @@ -201,9 +201,12 @@ fn cast_origin<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx>>( where Ctx::LookupError: From>, { - wrapped_origin(factory.clone(), move || { - cast_resolve(typeless_origin.clone(), factory.clone()) - }) + let origin_rb = typeless_origin.clone(); + wrapped_origin( + factory.clone(), + move || cast_resolve(typeless_origin.clone(), factory.clone()), + move || origin_rb.clone().resolve_bytes(), + ) } impl<'a, Ctx: Context<'a>> Point<'a, Ctx, TypelessMentionable<'a, Ctx>> diff --git a/src/rstd/local_origin.rs b/src/rstd/local_origin.rs index 926c79f..118dfc9 100644 --- a/src/rstd/local_origin.rs +++ b/src/rstd/local_origin.rs @@ -3,6 +3,9 @@ use std::rc::Rc; use crate::func::context::*; use crate::rcore::*; +use super::singular::*; +use super::*; + impl<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx>> Point<'a, Ctx, A> { fn prepare_bytes_for_hashing(mentioned: &A) -> Vec { let mut vec = mentioned.topology().to_vec(); @@ -38,6 +41,13 @@ impl<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx>> Origin<'a, Ctx> for LocalOri fn resolve(self: Rc) -> Resolution<'a, Ctx, Self::Mtbl> { Ctx::pure(Ok(self.0.clone())) } + + fn resolve_bytes(self: Rc) -> HashResolution<'a, Ctx> { + Ctx::pure(Ok(( + self.0.bytes(), + Rc::new(SingularResolver::from_mentionable(self.0.as_ref())), + ))) + } } impl From> for LocalOrigin { diff --git a/src/rstd/singular.rs b/src/rstd/singular.rs new file mode 100644 index 0000000..9bdadd7 --- /dev/null +++ b/src/rstd/singular.rs @@ -0,0 +1,59 @@ +use crate::rcore::*; +use crate::rstd::*; + +pub trait SingularResolution<'a, Ctx: Context<'a>>: 'a { + fn singular(self: Rc) -> HashResolution<'a, Ctx>; + + fn s_hash(&self) -> Hash; +} + +impl<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx>> SingularResolution<'a, Ctx> + for Point<'a, Ctx, A> +{ + fn singular(self: Rc) -> HashResolution<'a, Ctx> { + self.origin.clone().resolve_bytes() + } + + fn s_hash(&self) -> Hash { + self.point + } +} + +pub struct SingularResolver<'a, Ctx: Context<'a>> { + points: Vec>>, +} + +impl<'a, Ctx: Context<'a>> SingularResolver<'a, Ctx> { + pub fn from_mentionable>(a: &A) -> Self { + let mut points = Vec::new(); + a.points_typed(&mut points); + Self { points } + } +} + +impl<'a, Ctx: Context<'a>> Resolver<'a, Ctx> for SingularResolver<'a, Ctx> { + fn resolve(self: Rc, address: Address) -> HashResolution<'a, Ctx> { + let point = self.points.get(address.index).unwrap_or_else(|| { + panic!( + "singularity out-of-bounds: {}/{}.", + address.index, + self.points.len() + ) + }); + if point.s_hash() != address.point { + panic!( + "address mismatch at index {}: {}!={}", + address.index, + hex::encode(address.point), + hex::encode(point.s_hash()), + ) + } + point.clone().singular() + } +} + +impl<'a, Ctx: Context<'a>> TakesPoints<'a, Ctx> for Vec>> { + fn take>(&mut self, point: &Point<'a, Ctx, A>) { + self.push(Rc::new(point.clone()) as Rc>); + } +} diff --git a/src/rstd/wrapped_origin.rs b/src/rstd/wrapped_origin.rs index 8a46115..8eb5fdf 100644 --- a/src/rstd/wrapped_origin.rs +++ b/src/rstd/wrapped_origin.rs @@ -5,10 +5,12 @@ use super::*; pub fn wrapped_origin<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx>>( factory: A::Fctr, resolve: impl 'a + Fn() -> Resolution<'a, Ctx, A>, + resolve_bytes: impl 'a + Fn() -> HashResolution<'a, Ctx>, ) -> Rc> { Rc::new(WrappedOrigin { w_factory: factory, w_resolve: Box::new(resolve), + w_resolve_bytes: Box::new(resolve_bytes), }) } @@ -23,15 +25,17 @@ pub trait MappableOrigin<'a, Ctx: Context<'a>>: Origin<'a, Ctx> { + Fn(ParseError<'a, Ctx, OFctr<'a, Ctx, Self>>) -> ParseError<'a, Ctx, B::Fctr>, map_factory: impl 'a + FnOnce(OFctr<'a, Ctx, Self>) -> B::Fctr, ) -> Rc> { - let origin = self.clone(); + let origin_r = self.clone(); + let origin_rb = self.clone(); let origin: WrappedOrigin<'a, Ctx, B> = WrappedOrigin { w_factory: map_factory(self.factory()), w_resolve: Box::new(move || { - let origin = origin.clone(); + let origin = origin_r.clone(); let map_ok = map_ok.clone(); let map_err = map_err.clone(); map_resolve(move || origin.clone().resolve(), map_ok, map_err) }), + w_resolve_bytes: Box::new(move || origin_rb.clone().resolve_bytes()), }; Rc::new(origin) } @@ -53,6 +57,7 @@ fn map_resolve<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx>, B: Mentionable<'a, struct WrappedOrigin<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx>> { w_factory: A::Fctr, w_resolve: Box Resolution<'a, Ctx, A>>, + w_resolve_bytes: Box HashResolution<'a, Ctx>>, } impl<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx>> Origin<'a, Ctx> for WrappedOrigin<'a, Ctx, A> { @@ -65,4 +70,8 @@ impl<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx>> Origin<'a, Ctx> for WrappedO fn resolve(self: Rc) -> Resolution<'a, Ctx, A> { (self.w_resolve)() } + + fn resolve_bytes(self: Rc) -> HashResolution<'a, Ctx> { + (self.w_resolve_bytes)() + } }