diff options
Diffstat (limited to '')
-rw-r--r-- | vendor/anyhow/src/context.rs | 177 |
1 files changed, 177 insertions, 0 deletions
diff --git a/vendor/anyhow/src/context.rs b/vendor/anyhow/src/context.rs new file mode 100644 index 000000000..c2284130f --- /dev/null +++ b/vendor/anyhow/src/context.rs @@ -0,0 +1,177 @@ +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<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, + { + self.map_err(|error| error.ext_context(context)) + } + + fn with_context<C, F>(self, context: F) -> Result<T, Error> + 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<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, + { + self.ok_or_else(|| 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, + { + self.ok_or_else(|| 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, +{ + #[cfg(backtrace)] + fn backtrace(&self) -> Option<&Backtrace> { + self.error.backtrace() + } + + fn source(&self) -> Option<&(dyn StdError + 'static)> { + Some(&self.error) + } +} + +impl<C> StdError for ContextError<C, Error> +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>(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> {} +} |