Support nested details, add with_backtrace method to IntoContext, impl IntoContext for Detail

This commit is contained in:
Michael Pfaff 2023-07-02 12:07:00 -04:00
parent 184b334a09
commit 71385c9e19
Signed by: michael
GPG Key ID: CF402C4A012AA9D4
2 changed files with 31 additions and 10 deletions

View File

@ -4,7 +4,8 @@ fn main0() -> Result<()> {
Err(How::new(
"The engine broke down"
.with("Remember: you aren't good with cars")
.with("Suggestion: call a tow truck"),
.with("Suggestion: call a tow truck")
.with("Foo".with("Bar").with("Baz")),
)
.context(
"While driving down a road"

View File

@ -69,6 +69,7 @@ pub enum Detail {
#[cfg(feature = "backtrace")]
Backtrace(PrivateBacktrace),
Error(PrivateError),
Context(Box<Context>),
}
impl Detail {
@ -137,6 +138,7 @@ impl fmt::Display for Detail {
write!(f, "{}", bt)
},
Self::Error(PrivateError(e)) => e.fmt(f),
Self::Context(c) => c.fmt(f),
}
}
}
@ -154,6 +156,15 @@ pub trait IntoContext: Sized {
fn with_caller(self) -> Context {
self.with(Location::caller())
}
#[inline(always)]
#[track_caller]
fn with_backtrace(self) -> Context {
#[cfg(feature = "backtrace")]
return self.with(Detail::backtrace());
#[cfg(not(feature = "backtrace"))]
self.into_context()
}
}
impl IntoContext for Context {
@ -166,10 +177,12 @@ impl IntoContext for Context {
#[track_caller]
#[inline]
fn with(mut self, other: impl IntoContext) -> Self {
let mut other = other.into_context();
self.extra.reserve(1 + other.extra.len());
self.extra.push(other.detail);
self.extra.append(&mut other.extra);
let other = other.into_context();
if other.extra.is_empty() {
self.extra.push(other.detail);
} else {
self.extra.push(Detail::Context(other.into()));
}
self
}
}
@ -177,14 +190,14 @@ impl IntoContext for Context {
impl IntoContext for String {
#[inline(always)]
fn into_context(self) -> Context {
Context::new(Detail::String(self))
Detail::String(self).into_context()
}
}
impl IntoContext for &'static str {
#[inline(always)]
fn into_context(self) -> Context {
Context::new(Detail::Str(self))
Detail::Str(self).into_context()
}
}
@ -208,7 +221,7 @@ impl<'a> IntoContext for &'a Location<'static> {
impl IntoContext for Location<'static> {
#[inline]
fn into_context(self) -> Context {
Context::new(Detail::Location(self))
Detail::Location(self).into_context()
}
}
@ -218,14 +231,21 @@ where
{
#[inline]
fn into_context(self) -> Context {
Context::new(Detail::Error(PrivateError(self)))
Detail::Error(PrivateError(self)).into_context()
}
}
impl IntoContext for Arc<dyn std::error::Error + Send + Sync> {
#[inline]
fn into_context(self) -> Context {
Context::new(Detail::Error(PrivateError(self)))
Detail::Error(PrivateError(self)).into_context()
}
}
impl IntoContext for Detail {
#[inline(always)]
fn into_context(self) -> Context {
Context::new(self)
}
}