use std::fmt::Display;
use std::panic::Location;
use super::AppError;
use crate::{Enrichable, EnrichmentEntry};
#[expect(clippy::missing_errors_doc, reason = "documentation for errors is not required here")]
pub trait IntoAppError<T> {
fn into_app_err(self, msg: impl Display) -> Result<T, AppError>;
fn into_app_err_with<F, D>(self, msg_fn: F) -> Result<T, AppError>
where
F: FnOnce() -> D,
D: Display;
}
impl<T, E> IntoAppError<T> for Result<T, E>
where
E: std::error::Error + Send + Sync + 'static,
{
#[track_caller]
fn into_app_err(self, msg: impl Display) -> Result<T, AppError> {
match self {
Ok(value) => Ok(value),
Err(e) => {
let caller_location = Location::caller();
let mut app_err = AppError::new(e);
app_err.add_enrichment(EnrichmentEntry::new(
msg.to_string(),
caller_location.file(),
caller_location.line(),
));
Err(app_err)
}
}
}
#[track_caller]
fn into_app_err_with<F, D>(self, msg_fn: F) -> Result<T, AppError>
where
F: FnOnce() -> D,
D: Display,
{
match self {
Ok(value) => Ok(value),
Err(e) => {
let caller_location = Location::caller();
let mut app_err = AppError::new(e);
app_err.add_enrichment(EnrichmentEntry::new(
msg_fn().to_string(),
caller_location.file(),
caller_location.line(),
));
Err(app_err)
}
}
}
}
impl<T> IntoAppError<T> for Option<T> {
#[track_caller]
fn into_app_err(self, msg: impl Display) -> Result<T, AppError> {
self.ok_or_else(|| AppError::new(msg.to_string()))
}
#[track_caller]
fn into_app_err_with<F, D>(self, msg_fn: F) -> Result<T, AppError>
where
F: FnOnce() -> D,
D: Display,
{
self.ok_or_else(|| AppError::new(msg_fn().to_string()))
}
}
impl<T> IntoAppError<T> for Result<T, AppError> {
#[track_caller]
fn into_app_err(mut self, msg: impl Display) -> Self {
if let Err(e) = &mut self {
let caller_location = Location::caller();
e.add_enrichment(EnrichmentEntry::new(
msg.to_string(),
caller_location.file(),
caller_location.line(),
));
}
self
}
#[track_caller]
fn into_app_err_with<F, D>(mut self, msg_fn: F) -> Self
where
F: FnOnce() -> D,
D: Display,
{
if let Err(e) = &mut self {
let caller_location = Location::caller();
e.add_enrichment(EnrichmentEntry::new(
msg_fn().to_string(),
caller_location.file(),
caller_location.line(),
));
}
self
}
}