prolangkit 0.1.16

A set of language-agnostic utilities for langdev
Documentation
pub trait DebugWithContext<Ctx> {
    fn fmt(&self, ctx: &Ctx, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result;
}

pub trait DebugWithContextExt<Ctx>: DebugWithContext<Ctx> {
    fn dbg_ctx<'ctx, 't>(&'t self, ctx: &'ctx Ctx) -> ContextDebugger<'ctx, 't, Ctx, Self> {
        ContextDebugger { ctx, value: self }
    }
}

impl<T: ?Sized + DebugWithContext<Ctx>, Ctx> DebugWithContextExt<Ctx> for T {}

impl<'a, T: DebugWithContext<Ctx>, Ctx> DebugWithContext<Ctx> for &'a T {
    fn fmt(&self, ctx: &Ctx, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        T::fmt(self, ctx, f)
    }
}

pub struct ContextDebugger<'ctx, 't, C, T: ?Sized + DebugWithContext<C>> {
    pub ctx: &'ctx C,
    pub value: &'t T,
}

impl<C, T: ?Sized + DebugWithContext<C>> std::fmt::Debug for ContextDebugger<'_, '_, C, T> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        self.value.fmt(self.ctx, f)
    }
}

impl<C> DebugWithContext<C> for str {
    fn fmt(&self, _: &C, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.write_str(self)
    }
}

impl<C, T: DebugWithContext<C>> DebugWithContext<C> for Vec<T> {
    fn fmt(&self, ctx: &C, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        let mut list = f.debug_list();
        for elem in self.iter() {
            list.entry(&ContextDebugger { ctx, value: elem });
        }
        list.finish()
    }
}

impl<C, T: DebugWithContext<C>> DebugWithContext<C> for Option<T> {
    fn fmt(&self, ctx: &C, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            Some(val) => f.debug_tuple("Some").field(&val.dbg_ctx(ctx)).finish(),
            None => f.debug_struct("None").finish(),
        }
    }
}