use core::fmt::{Debug, Display, Formatter};
mod noop_cap_dev;
pub use noop_cap_dev::NoopCapDev;
pub struct DisplayToDebug<'a>(pub &'a dyn Display);
impl<'a> Debug for DisplayToDebug<'a> {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
write!(f, "{}", self.0)
}
}
pub trait DisplayExt {
fn as_display_debug(&self) -> DisplayToDebug<'_>;
}
impl<T> DisplayExt for T
where
T: Display,
{
fn as_display_debug(&self) -> DisplayToDebug<'_> {
DisplayToDebug(self)
}
}
pub trait ResultExt {
type T;
fn ok_trace(self) -> Option<Self::T>;
fn ok_ctx(self, ctx: impl Display) -> Option<Self::T>;
}
impl<T, E> ResultExt for Result<T, E>
where
E: Display,
{
type T = T;
fn ok_trace(self) -> Option<T> {
self.inspect_err(|e| tracing::error!(error = %e)).ok()
}
fn ok_ctx(self, ctx: impl Display) -> Option<T> {
self.inspect_err(|e| tracing::error!(error = %e, "{ctx}"))
.ok()
}
}
pub struct OptionDisplayDebug<'a, T>(pub &'a Option<T>);
impl<'a, T> Debug for OptionDisplayDebug<'a, T>
where
T: Display,
{
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
match self.0 {
Some(t) => t.fmt(f),
None => write!(f, "None"),
}
}
}
pub trait OptionExt {
type T;
fn trace_none(self, ctx: impl Display) -> Self;
fn map_display(&self) -> impl Debug
where
Self::T: Display;
}
impl<T> OptionExt for Option<T> {
type T = T;
fn trace_none(self, ctx: impl Display) -> Self {
if self.is_none() {
tracing::error!("{ctx}");
}
self
}
fn map_display(&self) -> impl Debug
where
T: Display,
{
OptionDisplayDebug(self)
}
}