diff --git a/src/explain.rs b/src/explain.rs index 1fdcaf3..a79e26c 100644 --- a/src/explain.rs +++ b/src/explain.rs @@ -25,17 +25,17 @@ where } } -impl Explain for Option -where - Option: IntoResultHow, -{ - type Output = Result<::T, How>; +impl Explain for Option { + type Output = Result; #[inline(always)] #[track_caller] fn context(self, context: impl IntoContext) -> Self::Output { - // TODO: maybe add a toggle for the extra "Option::None" context - //Err(How::new(context)) - self.into_result_how().map_err(#[inline(never)] move |e| e.context(context)) -} + // TODO: maybe add a feature for the extra "Option::None" context + match self { + Some(t) => Ok(t), + None => Err(How::new(context)) + } + //self.into_result_how().map_err(#[inline(never)] move |e| e.context(context)) } +} diff --git a/src/how.rs b/src/how.rs index 747872f..b1fd665 100644 --- a/src/how.rs +++ b/src/how.rs @@ -56,6 +56,46 @@ impl How { self.0.classified } + pub fn location(&self) -> &Context { + // SAFETY: we only ever push values into context, and the constructor ensures that there + // are at least 2 values in context. + let o = self.0.context.get(0); + if cfg!(debug_assertions) { + o.unwrap() + } else { + #[allow(unsafe_code)] + unsafe { o.unwrap_unchecked() } + } + } + + pub fn top(&self) -> &Context { + // SAFETY: we only ever push values into context, and the constructor ensures that there + // are at least 2 values in context. + let o = self.0.context.get(1); + if cfg!(debug_assertions) { + o.unwrap() + } else { + #[allow(unsafe_code)] + unsafe { o.unwrap_unchecked() } + } + } + + pub fn bottom(&self) -> &Context { + // SAFETY: we only ever push values into context, and the constructor ensures that there + // are at least 2 values in context. + let o = self.0.context.iter().next_back(); + if cfg!(debug_assertions) { + o.unwrap() + } else { + #[allow(unsafe_code)] + unsafe { o.unwrap_unchecked() } + } + } + + pub fn into_context(self) -> impl Iterator { + self.0.context.into_iter() + } + fn fmt_debug_alternate(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { let mut b = f.debug_struct(std::any::type_name::()); let b = b diff --git a/src/into.rs b/src/into.rs index 42b9fe0..20fd6c6 100644 --- a/src/into.rs +++ b/src/into.rs @@ -27,7 +27,10 @@ where fn into(e: E) -> How { How::new(e.to_string()) } - self.map_err(into) + match self { + Ok(t) => Ok(t), + Err(e) => Err(into(e)) + } } } @@ -51,6 +54,9 @@ impl IntoResultHow for Option { fn into() -> How { How::new("Option::None") } - self.ok_or_else(into) + match self { + Some(t) => Ok(t), + None => Err(into()) + } } } diff --git a/src/lib.rs b/src/lib.rs index a6b7fb2..e4e7637 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,5 @@ #![doc = include_str!("../README.md")] -#![forbid(unsafe_code)] +#![deny(unsafe_code)] #![feature(backtrace)] mod sealed;