194 lines
4.5 KiB
Rust
194 lines
4.5 KiB
Rust
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> {}
|
|
}
|