#![no_std]
pub trait OptionExt {
type Output;
fn unwrap_or_default_log(self) -> Self::Output;
fn unwrap_or_else_log(self, f: impl FnOnce() -> Self::Output) -> Self::Output;
fn unwrap_or_log(self, default: Self::Output) -> Self::Output;
}
pub trait ResultExt {
type Output;
fn unwrap_or_default_log(self) -> Self::Output;
fn unwrap_or_else_log(self, f: impl FnOnce() -> Self::Output) -> Self::Output;
fn unwrap_or_log(self, default: Self::Output) -> Self::Output;
}
pub trait ResultExtNoDbg {
type Output;
fn unwrap_or_default_log(self) -> Self::Output;
fn unwrap_or_else_log(self, f: impl FnOnce() -> Self::Output) -> Self::Output;
fn unwrap_or_log(self, default: Self::Output) -> Self::Output;
}
impl<T: Default> OptionExt for Option<T> {
type Output = T;
#[track_caller]
fn unwrap_or_default_log(self) -> T {
if let Some(x) = self {
x
} else {
option_error();
T::default()
}
}
#[track_caller]
fn unwrap_or_else_log(self, f: impl FnOnce() -> T) -> T {
if let Some(x) = self {
x
} else {
option_error();
f()
}
}
#[track_caller]
fn unwrap_or_log(self, default: T) -> T {
if let Some(x) = self {
x
} else {
option_error();
default
}
}
}
impl<T: Default, E: core::fmt::Debug> ResultExt for Result<T, E> {
type Output = T;
#[track_caller]
fn unwrap_or_default_log(self) -> T {
match self {
Ok(x) => x,
Err(err) => {
result_error(&err);
T::default()
}
}
}
#[track_caller]
fn unwrap_or_else_log(self, f: impl FnOnce() -> T) -> T {
match self {
Ok(x) => x,
Err(err) => {
result_error(&err);
f()
}
}
}
#[track_caller]
fn unwrap_or_log(self, default: T) -> T {
match self {
Ok(x) => x,
Err(err) => {
result_error(&err);
default
}
}
}
}
impl<T: Default, E> ResultExtNoDbg for Result<T, E> {
type Output = T;
#[track_caller]
fn unwrap_or_default_log(self) -> T {
if let Ok(x) = self {
x
} else {
no_dbg_error();
T::default()
}
}
#[track_caller]
fn unwrap_or_else_log(self, f: impl FnOnce() -> T) -> T {
if let Ok(x) = self {
x
} else {
no_dbg_error();
f()
}
}
#[track_caller]
fn unwrap_or_log(self, default: T) -> T {
if let Ok(x) = self {
x
} else {
no_dbg_error();
default
}
}
}
#[cold]
#[inline(never)]
#[track_caller]
fn option_error() {
let caller = core::panic::Location::caller();
log::warn!("{caller} encountered `None`");
}
#[cold]
#[inline(never)]
#[track_caller]
fn result_error(err: &dyn core::fmt::Debug) {
let caller = core::panic::Location::caller();
log::warn!("{caller} encountered `Err({err:?})`");
}
#[cold]
#[inline(never)]
#[track_caller]
fn no_dbg_error() {
let caller = core::panic::Location::caller();
log::warn!("{caller} encountered `Err(_)`");
}