use std::any::Any;
use std::fmt::{Debug, Display};
use crate::context::Context;
use crate::error::Error;
use crate::report::Report;
trait AnyReport: Send {
fn error_type_name(&self) -> &'static str;
fn error_message(&self) -> Option<&dyn Display>;
fn error_code(&self) -> Option<&'static str>;
fn error_any(&self) -> &dyn Any;
fn context(&self) -> &Context;
}
impl<E: Error> AnyReport for Report<E> {
fn error_type_name(&self) -> &'static str {
self.error().type_name()
}
fn error_message(&self) -> Option<&dyn Display> {
self.error().message()
}
fn error_code(&self) -> Option<&'static str> {
self.error().code()
}
fn error_any(&self) -> &dyn Any {
self.error()
}
fn context(&self) -> &Context {
self.context()
}
}
pub struct ErasedReport {
inner: Box<dyn AnyReport>,
}
impl ErasedReport {
#[must_use]
pub fn error_type_name(&self) -> &'static str {
self.inner.error_type_name()
}
#[must_use]
pub fn error_message(&self) -> Option<&dyn Display> {
self.inner.error_message()
}
#[must_use]
pub fn error_code(&self) -> Option<&'static str> {
self.inner.error_code()
}
#[must_use]
pub fn downcast_error<E: 'static>(&self) -> Option<&E> {
self.inner.error_any().downcast_ref()
}
#[must_use]
pub fn context(&self) -> &Context {
self.inner.context()
}
}
impl Debug for ErasedReport {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("ErasedReport")
.field("error_type", &self.error_type_name())
.finish_non_exhaustive()
}
}
impl<E: Error> From<Report<E>> for ErasedReport {
fn from(report: Report<E>) -> Self {
ErasedReport {
inner: Box::new(report),
}
}
}
impl<E: Error> From<E> for ErasedReport {
#[track_caller]
fn from(error: E) -> Self {
Report::new(error).into()
}
}