use crate::error::ContextError; use crate::{Context, Error, StdError}; use core::convert::Infallible; use core::fmt::{self, Debug, Display, Write}; #[cfg(backtrace)] use std::backtrace::Backtrace; mod ext { use super::*; pub trait StdError { fn ext_context(self, context: C) -> Error where C: Display + Send + Sync + 'static; } #[cfg(feature = "std")] impl StdError for E where E: std::error::Error + Send + Sync + 'static, { fn ext_context(self, context: C) -> Error where C: Display + Send + Sync + 'static, { let backtrace = backtrace_if_absent!(self); Error::from_context(context, self, backtrace) } } impl StdError for Error { fn ext_context(self, context: C) -> Error where C: Display + Send + Sync + 'static, { self.context(context) } } } impl Context for Result where E: ext::StdError + Send + Sync + 'static, { fn context(self, context: C) -> Result where C: Display + Send + Sync + 'static, { self.map_err(|error| error.ext_context(context)) } fn with_context(self, context: F) -> Result where C: Display + Send + Sync + 'static, F: FnOnce() -> C, { self.map_err(|error| error.ext_context(context())) } } /// ``` /// # type T = (); /// # /// use anyhow::{Context, Result}; /// /// fn maybe_get() -> Option { /// # const IGNORE: &str = stringify! { /// ... /// # }; /// # unimplemented!() /// } /// /// fn demo() -> Result<()> { /// let t = maybe_get().context("there is no T")?; /// # const IGNORE: &str = stringify! { /// ... /// # }; /// # unimplemented!() /// } /// ``` impl Context for Option { fn context(self, context: C) -> Result where C: Display + Send + Sync + 'static, { self.ok_or_else(|| Error::from_display(context, backtrace!())) } fn with_context(self, context: F) -> Result where C: Display + Send + Sync + 'static, F: FnOnce() -> C, { self.ok_or_else(|| Error::from_display(context(), backtrace!())) } } impl Debug for ContextError where C: Display, E: Debug, { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("Error") .field("context", &Quoted(&self.context)) .field("source", &self.error) .finish() } } impl Display for ContextError where C: Display, { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { Display::fmt(&self.context, f) } } impl StdError for ContextError where C: Display, E: StdError + 'static, { #[cfg(backtrace)] fn backtrace(&self) -> Option<&Backtrace> { self.error.backtrace() } fn source(&self) -> Option<&(dyn StdError + 'static)> { Some(&self.error) } } impl StdError for ContextError where C: Display, { #[cfg(backtrace)] fn backtrace(&self) -> Option<&Backtrace> { Some(self.error.backtrace()) } fn source(&self) -> Option<&(dyn StdError + 'static)> { Some(unsafe { crate::ErrorImpl::error(self.error.inner.by_ref()) }) } } struct Quoted(C); impl Debug for Quoted where C: Display, { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_char('"')?; Quoted(&mut *formatter).write_fmt(format_args!("{}", self.0))?; formatter.write_char('"')?; Ok(()) } } impl Write for Quoted<&mut fmt::Formatter<'_>> { fn write_str(&mut self, s: &str) -> fmt::Result { Display::fmt(&s.escape_debug(), self.0) } } pub(crate) mod private { use super::*; pub trait Sealed {} impl Sealed for Result where E: ext::StdError {} impl Sealed for Option {} }