| use crate::error::ContextError; | |
| use crate::{Context, Error, StdError}; | |
| use core::convert::Infallible; | |
| use core::fmt::{self, Debug, Display, Write}; | |
| #[cfg(backtrace)] | |
| use std::error::Request; | |
| 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, request: &mut Request<'a>) { | |
| StdError::provide(&self.error, request); | |
| } | |
| } | |
| 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, request: &mut Request<'a>) { | |
| Error::provide(&self.error, request); | |
| } | |
| } | |
| 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> {} | |
| } |