feat: Implement `WrapError` for `Option`

Implement `WrapError` for `Option<T>`. This is inline with `anyhow` that
also implements `Context` for `Option<T>`.

The implementation requires us to introduce a `DisplayError` internal
only type, that creates an error from a type that only implements
`Display` (`Report::from_adhoc` requires the type to also implement
`Debug`, but `WrapError` only requires it to implement `Display`).

For this I copied `MessageError` and adapted it to implement `Debug`
using the underlying type's `Display` impl. This is a bit of a hack, but
anyhow does [something similar][1].

Closes #408

[1]: https://docs.rs/anyhow/latest/src/anyhow/wrapper.rs.html#34
This commit is contained in:
Jalil David Salamé Messina 2024-11-16 17:36:58 +01:00
parent 2902a2337c
commit 64f20e66e4
No known key found for this signature in database
GPG Key ID: F016B9E770737A0B
2 changed files with 62 additions and 0 deletions

View File

@ -38,6 +38,44 @@ mod ext {
}
}
impl<T> WrapErr<T, std::convert::Infallible> for Option<T> {
fn wrap_err<D>(self, msg: D) -> Result<T, Report>
where
D: Display + Send + Sync + 'static,
{
match self {
Some(t) => Ok(t),
None => Err(Report::from(crate::eyreish::wrapper::DisplayError(msg))),
}
}
fn wrap_err_with<D, F>(self, msg: F) -> Result<T, Report>
where
D: Display + Send + Sync + 'static,
F: FnOnce() -> D,
{
match self {
Some(t) => Ok(t),
None => Err(Report::from(crate::eyreish::wrapper::DisplayError(msg()))),
}
}
fn context<D>(self, msg: D) -> Result<T, Report>
where
D: Display + Send + Sync + 'static,
{
self.wrap_err(msg)
}
fn with_context<D, F>(self, msg: F) -> Result<T, Report>
where
D: Display + Send + Sync + 'static,
F: FnOnce() -> D,
{
self.wrap_err_with(msg)
}
}
impl<T, E> WrapErr<T, E> for Result<T, E>
where
E: ext::Diag + Send + Sync + 'static,

View File

@ -6,6 +6,30 @@ use crate::{Diagnostic, LabeledSpan, Report, SourceCode};
use crate as miette;
#[repr(transparent)]
pub(crate) struct DisplayError<M>(pub(crate) M);
impl<M> Debug for DisplayError<M>
where
M: Display,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
Display::fmt(&self.0, f)
}
}
impl<M> Display for DisplayError<M>
where
M: Display,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
Display::fmt(&self.0, f)
}
}
impl<M> StdError for DisplayError<M> where M: Display + 'static {}
impl<M> Diagnostic for DisplayError<M> where M: Display + 'static {}
#[repr(transparent)]
pub(crate) struct MessageError<M>(pub(crate) M);