radn-rs/src/rstd/singular.rs

60 lines
1.7 KiB
Rust

use crate::rcore::*;
use crate::rstd::*;
trait SingularResolution<'a, Ctx: Context<'a>>: 'a {
fn singular(self: Rc<Self>) -> 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<Self>) -> HashResolution<'a, Ctx> {
self.origin.clone().resolve_bytes()
}
fn s_hash(&self) -> Hash {
self.point
}
}
pub struct SingularResolver<'a, Ctx: Context<'a>> {
points: Vec<Rc<dyn SingularResolution<'a, Ctx>>>,
}
impl<'a, Ctx: Context<'a>> SingularResolver<'a, Ctx> {
pub fn from_mentionable<A: Mentionable<'a, Ctx>>(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<Self>, 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>> PointsVisitor<'a, Ctx> for Vec<Rc<dyn SingularResolution<'a, Ctx>>> {
fn visit<A: Mentionable<'a, Ctx>>(&mut self, point: &Point<'a, Ctx, A>) {
self.push(Rc::new(point.clone()) as _);
}
}