From 7fae60fd8462f95cf3140c6a3b9eb06cb7953405 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jalil=20David=20Salam=C3=A9=20Messina?= <60845989+jalil-salame@users.noreply.github.com> Date: Wed, 27 Nov 2024 04:55:24 +0100 Subject: [PATCH] feat(report): Implement `WrapError` for `Option` (#409) Fixes: https://github.com/zkat/miette/issues/408 Implement `WrapError` for `Option`. This is inline with `anyhow` that also implements `Context` for `Option`. 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]. [1]: https://docs.rs/anyhow/latest/src/anyhow/wrapper.rs.html#34 --- src/eyreish/context.rs | 38 ++++++++++++++++++++++++++++++++++++++ src/eyreish/wrapper.rs | 24 ++++++++++++++++++++++++ 2 files changed, 62 insertions(+) diff --git a/src/eyreish/context.rs b/src/eyreish/context.rs index 3d9238b2..ee1fa08d 100644 --- a/src/eyreish/context.rs +++ b/src/eyreish/context.rs @@ -38,6 +38,44 @@ mod ext { } } +impl WrapErr for Option { + fn wrap_err(self, msg: D) -> Result + 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(self, msg: F) -> Result + 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(self, msg: D) -> Result + where + D: Display + Send + Sync + 'static, + { + self.wrap_err(msg) + } + + fn with_context(self, msg: F) -> Result + where + D: Display + Send + Sync + 'static, + F: FnOnce() -> D, + { + self.wrap_err_with(msg) + } +} + impl WrapErr for Result where E: ext::Diag + Send + Sync + 'static, diff --git a/src/eyreish/wrapper.rs b/src/eyreish/wrapper.rs index 62cf7a4b..bab73208 100644 --- a/src/eyreish/wrapper.rs +++ b/src/eyreish/wrapper.rs @@ -6,6 +6,30 @@ use crate::{Diagnostic, LabeledSpan, Report, SourceCode}; use crate as miette; +#[repr(transparent)] +pub(crate) struct DisplayError(pub(crate) M); + +impl Debug for DisplayError +where + M: Display, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + Display::fmt(&self.0, f) + } +} + +impl Display for DisplayError +where + M: Display, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + Display::fmt(&self.0, f) + } +} + +impl StdError for DisplayError where M: Display + 'static {} +impl Diagnostic for DisplayError where M: Display + 'static {} + #[repr(transparent)] pub(crate) struct MessageError(pub(crate) M);