#![cfg_attr(doc_cfg, feature(doc_cfg))]
#![allow(
clippy::needless_doctest_main,
clippy::new_ret_no_self,
clippy::wrong_self_convention
)]
use core::fmt::Display;
use std::error::Error as StdError;
use once_cell::sync::OnceCell;
#[allow(unreachable_pub)]
pub use into_diagnostic::*;
#[doc(hidden)]
#[allow(unreachable_pub)]
pub use Report as ErrReport;
#[allow(unreachable_pub)]
pub use Report as Error;
#[doc(hidden)]
#[allow(unreachable_pub)]
pub use ReportHandler as EyreContext;
#[allow(unreachable_pub)]
pub use WrapErr as Context;
#[cfg(not(feature = "fancy-no-backtrace"))]
use crate::DebugReportHandler;
use crate::Diagnostic;
#[cfg(feature = "fancy-no-backtrace")]
use crate::MietteHandler;
use error::ErrorImpl;
use self::ptr::Own;
mod context;
mod error;
mod fmt;
mod into_diagnostic;
mod kind;
mod macros;
mod ptr;
mod wrapper;
pub struct Report {
inner: Own<ErrorImpl<()>>,
}
unsafe impl Sync for Report {}
unsafe impl Send for Report {}
pub type ErrorHook =
Box<dyn Fn(&(dyn Diagnostic + 'static)) -> Box<dyn ReportHandler> + Sync + Send + 'static>;
static HOOK: OnceCell<ErrorHook> = OnceCell::new();
#[derive(Debug)]
pub struct InstallError;
impl core::fmt::Display for InstallError {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.write_str("cannot install provided ErrorHook, a hook has already been installed")
}
}
impl StdError for InstallError {}
impl Diagnostic for InstallError {}
pub fn set_hook(hook: ErrorHook) -> Result<(), InstallError> {
HOOK.set(hook).map_err(|_| InstallError)
}
#[cfg_attr(track_caller, track_caller)]
#[cfg_attr(not(track_caller), allow(unused_mut))]
fn capture_handler(error: &(dyn Diagnostic + 'static)) -> Box<dyn ReportHandler> {
let hook = HOOK.get_or_init(|| Box::new(get_default_printer)).as_ref();
#[cfg(track_caller)]
{
let mut handler = hook(error);
handler.track_caller(std::panic::Location::caller());
handler
}
#[cfg(not(track_caller))]
{
hook(error)
}
}
fn get_default_printer(_err: &(dyn Diagnostic + 'static)) -> Box<dyn ReportHandler + 'static> {
#[cfg(feature = "fancy-no-backtrace")]
return Box::new(MietteHandler::new());
#[cfg(not(feature = "fancy-no-backtrace"))]
return Box::new(DebugReportHandler::new());
}
impl dyn ReportHandler {
pub fn is<T: ReportHandler>(&self) -> bool {
let t = core::any::TypeId::of::<T>();
let concrete = self.type_id();
t == concrete
}
pub fn downcast_ref<T: ReportHandler>(&self) -> Option<&T> {
if self.is::<T>() {
unsafe { Some(&*(self as *const dyn ReportHandler as *const T)) }
} else {
None
}
}
pub fn downcast_mut<T: ReportHandler>(&mut self) -> Option<&mut T> {
if self.is::<T>() {
unsafe { Some(&mut *(self as *mut dyn ReportHandler as *mut T)) }
} else {
None
}
}
}
pub trait ReportHandler: core::any::Any + Send + Sync {
fn debug(
&self,
error: &(dyn Diagnostic),
f: &mut core::fmt::Formatter<'_>,
) -> core::fmt::Result;
fn display(
&self,
error: &(dyn StdError + 'static),
f: &mut core::fmt::Formatter<'_>,
) -> core::fmt::Result {
write!(f, "{}", error)?;
if f.alternate() {
for cause in crate::chain::Chain::new(error).skip(1) {
write!(f, ": {}", cause)?;
}
}
Ok(())
}
#[allow(unused_variables)]
fn track_caller(&mut self, location: &'static std::panic::Location<'static>) {}
}
pub type Result<T, E = Report> = core::result::Result<T, E>;
pub trait WrapErr<T, E>: context::private::Sealed {
#[cfg_attr(track_caller, track_caller)]
fn wrap_err<D>(self, msg: D) -> Result<T, Report>
where
D: Display + Send + Sync + 'static;
#[cfg_attr(track_caller, track_caller)]
fn wrap_err_with<D, F>(self, f: F) -> Result<T, Report>
where
D: Display + Send + Sync + 'static,
F: FnOnce() -> D;
#[cfg_attr(track_caller, track_caller)]
fn context<D>(self, msg: D) -> Result<T, Report>
where
D: Display + Send + Sync + 'static;
#[cfg_attr(track_caller, track_caller)]
fn with_context<D, F>(self, f: F) -> Result<T, Report>
where
D: Display + Send + Sync + 'static,
F: FnOnce() -> D;
}
#[doc(hidden)]
pub mod private {
use super::Report;
use core::fmt::{Debug, Display};
pub use core::result::Result::Err;
#[doc(hidden)]
pub mod kind {
pub use super::super::kind::{AdhocKind, TraitKind};
pub use super::super::kind::BoxedKind;
}
#[cfg_attr(track_caller, track_caller)]
pub fn new_adhoc<M>(message: M) -> Report
where
M: Display + Debug + Send + Sync + 'static,
{
Report::from_adhoc(message)
}
}