use std::fmt;
use std::sync::{OnceLock, RwLock};
use miette::{Diagnostic, GraphicalReportHandler, ReportHandler};
type Footer = Box<dyn Fn() -> String + Send + Sync + 'static>;
static FOOTER: OnceLock<RwLock<Option<Footer>>> = OnceLock::new();
fn footer_slot() -> &'static RwLock<Option<Footer>> {
FOOTER.get_or_init(|| RwLock::new(None))
}
pub fn install_report_handler() {
let _ = footer_slot();
let _ = miette::set_hook(Box::new(|_| Box::new(RtbReportHandler::new())));
}
pub fn install_panic_hook() {
miette::set_panic_hook();
}
pub fn install_with_footer<F>(footer: F)
where
F: Fn() -> String + Send + Sync + 'static,
{
install_report_handler();
let mut guard =
footer_slot().write().expect("footer lock poisoned — another thread panicked mid-update");
*guard = Some(Box::new(footer));
}
struct RtbReportHandler {
inner: GraphicalReportHandler,
}
impl RtbReportHandler {
fn new() -> Self {
Self { inner: GraphicalReportHandler::new() }
}
}
thread_local! {
static IN_RENDER: std::cell::Cell<bool> = const { std::cell::Cell::new(false) };
}
impl ReportHandler for RtbReportHandler {
fn debug(&self, diagnostic: &dyn Diagnostic, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.inner.render_report(f, diagnostic)?;
if IN_RENDER.with(std::cell::Cell::get) {
return Ok(());
}
let maybe_text = {
let Some(slot) = FOOTER.get() else {
return Ok(());
};
let Ok(guard) = slot.read() else {
return Ok(());
};
let Some(footer) = guard.as_ref() else {
return Ok(());
};
IN_RENDER.with(|flag| flag.set(true));
#[allow(clippy::redundant_closure)]
let outcome = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| footer()));
IN_RENDER.with(|flag| flag.set(false));
outcome.ok()
};
if let Some(text) = maybe_text {
if !text.is_empty() {
writeln!(f)?;
writeln!(f, "{text}")?;
}
}
Ok(())
}
}