| use crate::error::ContextError; |
| use crate::{Context, Error, StdError}; |
| use core::convert::Infallible; |
| use core::fmt::{self, Debug, Display, Write}; |
| |
| #[cfg(backtrace)] |
| use std::any::{Demand, Provider}; |
| |
| mod ext { |
| use super::*; |
| |
| pub trait StdError { |
| fn ext_context<C>(self, context: C) -> Error |
| where |
| C: Display + Send + Sync + 'static; |
| } |
| |
| #[cfg(feature = "std")] |
| impl<E> StdError for E |
| where |
| E: std::error::Error + Send + Sync + 'static, |
| { |
| fn ext_context<C>(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<C>(self, context: C) -> Error |
| where |
| C: Display + Send + Sync + 'static, |
| { |
| self.context(context) |
| } |
| } |
| } |
| |
| impl<T, E> Context<T, E> for Result<T, E> |
| where |
| E: ext::StdError + Send + Sync + 'static, |
| { |
| fn context<C>(self, context: C) -> Result<T, Error> |
| where |
| C: Display + Send + Sync + 'static, |
| { |
| // Not using map_err to save 2 useless frames off the captured backtrace |
| // in ext_context. |
| match self { |
| Ok(ok) => Ok(ok), |
| Err(error) => Err(error.ext_context(context)), |
| } |
| } |
| |
| fn with_context<C, F>(self, context: F) -> Result<T, Error> |
| where |
| C: Display + Send + Sync + 'static, |
| F: FnOnce() -> C, |
| { |
| match self { |
| Ok(ok) => Ok(ok), |
| Err(error) => Err(error.ext_context(context())), |
| } |
| } |
| } |
| |
| /// ``` |
| /// # type T = (); |
| /// # |
| /// use anyhow::{Context, Result}; |
| /// |
| /// fn maybe_get() -> Option<T> { |
| /// # const IGNORE: &str = stringify! { |
| /// ... |
| /// # }; |
| /// # unimplemented!() |
| /// } |
| /// |
| /// fn demo() -> Result<()> { |
| /// let t = maybe_get().context("there is no T")?; |
| /// # const IGNORE: &str = stringify! { |
| /// ... |
| /// # }; |
| /// # unimplemented!() |
| /// } |
| /// ``` |
| impl<T> Context<T, Infallible> for Option<T> { |
| fn context<C>(self, context: C) -> Result<T, Error> |
| where |
| C: Display + Send + Sync + 'static, |
| { |
| // Not using ok_or_else to save 2 useless frames off the captured |
| // backtrace. |
| match self { |
| Some(ok) => Ok(ok), |
| None => Err(Error::from_display(context, backtrace!())), |
| } |
| } |
| |
| fn with_context<C, F>(self, context: F) -> Result<T, Error> |
| where |
| C: Display + Send + Sync + 'static, |
| F: FnOnce() -> C, |
| { |
| match self { |
| Some(ok) => Ok(ok), |
| None => Err(Error::from_display(context(), backtrace!())), |
| } |
| } |
| } |
| |
| impl<C, E> Debug for ContextError<C, E> |
| 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<C, E> Display for ContextError<C, E> |
| where |
| C: Display, |
| { |
| fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
| Display::fmt(&self.context, f) |
| } |
| } |
| |
| impl<C, E> StdError for ContextError<C, E> |
| where |
| C: Display, |
| E: StdError + 'static, |
| { |
| fn source(&self) -> Option<&(dyn StdError + 'static)> { |
| Some(&self.error) |
| } |
| |
| #[cfg(backtrace)] |
| fn provide<'a>(&'a self, demand: &mut Demand<'a>) { |
| StdError::provide(&self.error, demand); |
| } |
| } |
| |
| impl<C> StdError for ContextError<C, Error> |
| where |
| C: Display, |
| { |
| fn source(&self) -> Option<&(dyn StdError + 'static)> { |
| Some(unsafe { crate::ErrorImpl::error(self.error.inner.by_ref()) }) |
| } |
| |
| #[cfg(backtrace)] |
| fn provide<'a>(&'a self, demand: &mut Demand<'a>) { |
| Provider::provide(&self.error, demand); |
| } |
| } |
| |
| struct Quoted<C>(C); |
| |
| impl<C> Debug for Quoted<C> |
| 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<T, E> Sealed for Result<T, E> where E: ext::StdError {} |
| impl<T> Sealed for Option<T> {} |
| } |