Add an Error element
This commit is contained in:
parent
f416f66d5c
commit
639e5835e4
|
@ -3,6 +3,7 @@ use std::borrow::Cow;
|
||||||
use std::backtrace::BacktraceStatus;
|
use std::backtrace::BacktraceStatus;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::panic::Location;
|
use std::panic::Location;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
/// Provides context furthering the explanation of *how* you got to an error.
|
/// Provides context furthering the explanation of *how* you got to an error.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -31,6 +32,7 @@ pub(crate) enum ContextElem {
|
||||||
Location(Location<'static>),
|
Location(Location<'static>),
|
||||||
#[cfg(feature = "backtrace")]
|
#[cfg(feature = "backtrace")]
|
||||||
Backtrace(Backtrace),
|
Backtrace(Backtrace),
|
||||||
|
Error(Arc<dyn std::error::Error + Send + Sync>),
|
||||||
}
|
}
|
||||||
|
|
||||||
// will be replaced with std::backtrace::Backtrace if and when it is Clone
|
// will be replaced with std::backtrace::Backtrace if and when it is Clone
|
||||||
|
@ -86,6 +88,7 @@ impl fmt::Display for ContextElem {
|
||||||
})?;
|
})?;
|
||||||
write!(f, "{}", bt)
|
write!(f, "{}", bt)
|
||||||
},
|
},
|
||||||
|
Self::Error(e) => e.fmt(f),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
use std::panic::Location;
|
use std::panic::Location;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
use crate::{How, IntoContext};
|
use crate::{How, IntoContext};
|
||||||
|
use crate::context::*;
|
||||||
|
|
||||||
pub trait Explain {
|
pub trait Explain {
|
||||||
type Output;
|
type Output;
|
||||||
|
@ -16,7 +18,6 @@ impl Explain for How {
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
#[inline]
|
#[inline]
|
||||||
fn context(mut self, context: impl IntoContext) -> Self {
|
fn context(mut self, context: impl IntoContext) -> Self {
|
||||||
use crate::context::*;
|
|
||||||
let mut context = context.into_context();
|
let mut context = context.into_context();
|
||||||
let loc = ContextElem::Location(*Location::caller());
|
let loc = ContextElem::Location(*Location::caller());
|
||||||
#[cfg(feature = "backtrace")]
|
#[cfg(feature = "backtrace")]
|
||||||
|
@ -65,6 +66,9 @@ where
|
||||||
{
|
{
|
||||||
match typeid_cast::cast(e) {
|
match typeid_cast::cast(e) {
|
||||||
Ok(e) => e,
|
Ok(e) => e,
|
||||||
|
// TODO: specialize on Send + Sync at runtime or compile time (possibly via
|
||||||
|
// specialization)
|
||||||
|
//Err(e) => How::new(Context(ContextInner::Elem(ContextElem::Error(Arc::new(e))))),
|
||||||
Err(e) => How::new(e.to_string()),
|
Err(e) => How::new(e.to_string()),
|
||||||
}
|
}
|
||||||
.context(c)
|
.context(c)
|
||||||
|
@ -76,17 +80,28 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<E> Explain for Arc<E>
|
||||||
|
where
|
||||||
|
E: std::error::Error + Send + Sync + 'static,
|
||||||
|
{
|
||||||
|
type Output = How;
|
||||||
|
|
||||||
|
#[track_caller]
|
||||||
|
fn context(self, context: impl IntoContext) -> Self::Output {
|
||||||
|
How::new(Context(ContextInner::Elem(ContextElem::Error(self))))
|
||||||
|
.context(context)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<T> Explain for Option<T> {
|
impl<T> Explain for Option<T> {
|
||||||
type Output = Result<T, How>;
|
type Output = Result<T, How>;
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
fn context(self, context: impl IntoContext) -> Self::Output {
|
fn context(self, context: impl IntoContext) -> Self::Output {
|
||||||
// TODO: maybe add a feature for the extra "Option::None" context
|
|
||||||
match self {
|
match self {
|
||||||
Some(t) => Ok(t),
|
Some(t) => Ok(t),
|
||||||
None => Err(How::new(context)),
|
None => Err(How::new(context)),
|
||||||
}
|
}
|
||||||
//self.into_result_how().map_err(#[inline(never)] move |e| e.context(context))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue