use std::error::Error;
use std::fmt;
use anyerror::AnyError;
use crate::OptionalSend;
use crate::OptionalSync;
use crate::base::OptionalSerde;
pub trait ErrorSource: Error + Clone + PartialEq + Eq + OptionalSend + OptionalSync + OptionalSerde + 'static {
fn from_error<E: Error + 'static>(error: &E) -> Self;
fn from_string(msg: impl ToString) -> Self;
fn has_backtrace(&self) -> bool {
false
}
fn fmt_backtrace(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
Ok(())
}
}
impl ErrorSource for AnyError {
fn from_error<E: Error + 'static>(error: &E) -> Self {
AnyError::new(error)
}
fn from_string(msg: impl ToString) -> Self {
AnyError::error(msg)
}
fn has_backtrace(&self) -> bool {
anyerror::backtrace_str().is_some()
}
fn fmt_backtrace(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if let Some(bt) = anyerror::backtrace_str() {
write!(f, "{}", bt)
} else {
Ok(())
}
}
}
pub struct BacktraceDisplay<'a, E: ErrorSource>(pub &'a E);
impl<E: ErrorSource> fmt::Display for BacktraceDisplay<'_, E> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if self.0.has_backtrace() {
self.0.fmt_backtrace(f)
} else {
Ok(())
}
}
}