use alloc::{borrow::Cow, boxed::Box};
use core::{error::Error, fmt::Display};
use crate::{
SimpleError, UniResult,
cause::{CauseInner, UniDisplay, UniStdError},
error::UniError,
kind::{UniKind, UniKindCode, UniKindCodes},
};
impl<K: Default, E: UniStdError> From<E> for UniError<K> {
fn from(err: E) -> Self {
ErrorContext::kind_default(err)
}
}
impl<E: UniStdError> From<E> for UniError<dyn UniKind> {
fn from(err: E) -> Self {
SimpleError::from(err).into()
}
}
impl<K: UniKind> From<UniError<K>> for UniError<dyn UniKind> {
fn from(err: UniError<K>) -> Self {
err.into_dyn_kind()
}
}
impl<K: UniKindCode> From<UniError<K>> for UniError<dyn UniKindCode<Code = K::Code>> {
fn from(err: UniError<K>) -> Self {
err.into_dyn_kind_code()
}
}
impl<K: UniKindCodes> From<UniError<K>>
for UniError<dyn UniKindCodes<Code = K::Code, Code2 = K::Code2>>
{
fn from(err: UniError<K>) -> Self {
err.into_dyn_kind_codes()
}
}
#[cfg(any(feature = "http_code", feature = "axum_code"))]
impl<K: UniKindCode<Code = http::StatusCode> + ?Sized> From<UniError<K>>
for (http::StatusCode, alloc::string::String)
{
fn from(err: UniError<K>) -> Self {
(
err.typed_code(),
<UniError<K> as alloc::string::ToString>::to_string(&err),
)
}
}
#[cfg(any(feature = "http_code2", feature = "axum_code2"))]
impl<K: UniKindCodes<Code2 = http::StatusCode> + ?Sized> From<UniError<K>>
for (http::StatusCode, alloc::string::String)
{
fn from(err: UniError<K>) -> Self {
(
err.typed_code2(),
<UniError<K> as alloc::string::ToString>::to_string(&err),
)
}
}
#[cfg(feature = "tonic_code")]
impl<K: UniKindCode<Code = tonic::Code> + ?Sized> From<UniError<K>>
for (tonic::Code, alloc::string::String)
{
fn from(err: UniError<K>) -> Self {
(
err.typed_code(),
<UniError<K> as alloc::string::ToString>::to_string(&err),
)
}
}
#[cfg(feature = "tonic_code")]
impl<K: UniKindCode<Code = tonic::Code> + ?Sized> From<UniError<K>> for tonic::Status {
fn from(err: UniError<K>) -> Self {
tonic::Status::new(
err.typed_code(),
<UniError<K> as alloc::string::ToString>::to_string(&err),
)
}
}
#[cfg(feature = "tonic_code2")]
impl<K: UniKindCodes<Code2 = tonic::Code> + ?Sized> From<UniError<K>>
for (tonic::Code, alloc::string::String)
{
fn from(err: UniError<K>) -> Self {
(
err.typed_code2(),
<UniError<K> as alloc::string::ToString>::to_string(&err),
)
}
}
#[cfg(feature = "tonic_code2")]
impl<K: UniKindCodes<Code2 = tonic::Code> + ?Sized> From<UniError<K>> for tonic::Status {
fn from(err: UniError<K>) -> Self {
tonic::Status::new(
err.typed_code2(),
<UniError<K> as alloc::string::ToString>::to_string(&err),
)
}
}
#[cfg(feature = "axum_code")]
impl<K: UniKindCode<Code = http::StatusCode> + ?Sized> axum::response::IntoResponse
for UniError<K>
{
fn into_response(self) -> axum::response::Response {
(
self.typed_code(),
<UniError<K> as alloc::string::ToString>::to_string(&self),
)
.into_response()
}
}
#[cfg(feature = "axum_code2")]
impl<K: UniKindCodes<Code2 = http::StatusCode> + ?Sized> axum::response::IntoResponse
for UniError<K>
{
fn into_response(self) -> axum::response::Response {
(
self.typed_code2(),
<UniError<K> as alloc::string::ToString>::to_string(&self),
)
.into_response()
}
}
#[derive(Debug)]
pub struct StdErrorWrapper<K: ?Sized>(pub UniError<K>);
impl<K: UniKind + ?Sized> Display for StdErrorWrapper<K> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
Display::fmt(&self.0, f)
}
}
impl<K: UniKind + ?Sized> Error for StdErrorWrapper<K> {
fn source(&self) -> Option<&(dyn Error + 'static)> {
self.0.source()
}
}
impl<K: UniKind + ?Sized> From<UniError<K>> for Box<dyn Error + Send + Sync> {
fn from(err: UniError<K>) -> Self {
Box::new(StdErrorWrapper(err))
}
}
pub trait ErrorContext<K> {
fn kind(self, kind: K) -> UniError<K>;
fn kind_default_context(self, context: impl Into<Cow<'static, str>>) -> UniError<K>
where
K: Default;
fn kind_context(self, kind: K, context: impl Into<Cow<'static, str>>) -> UniError<K>;
fn kind_default(self) -> UniError<K>
where
K: Default;
}
impl<K, E: UniStdError> ErrorContext<K> for E {
fn kind(self, kind: K) -> UniError<K> {
UniError::new(kind, None, Some(CauseInner::from_error(self)))
}
fn kind_default_context(self, context: impl Into<Cow<'static, str>>) -> UniError<K>
where
K: Default,
{
UniError::new(
Default::default(),
Some(context.into()),
Some(CauseInner::from_error(self)),
)
}
fn kind_context(self, kind: K, context: impl Into<Cow<'static, str>>) -> UniError<K> {
UniError::new(
kind,
Some(context.into()),
Some(CauseInner::from_error(self)),
)
}
fn kind_default(self) -> UniError<K>
where
K: Default,
{
UniError::new(Default::default(), None, Some(CauseInner::from_error(self)))
}
}
pub trait ResultContext<K, T> {
fn kind(self, kind: K) -> UniResult<T, K>;
fn kind_default_context(self, context: impl Into<Cow<'static, str>>) -> UniResult<T, K>
where
K: Default;
fn kind_context(self, kind: K, context: impl Into<Cow<'static, str>>) -> UniResult<T, K>;
fn kind_fn<F>(self, kind: F) -> UniResult<T, K>
where
F: FnOnce() -> K;
fn kind_default_context_fn<F, S>(self, context: F) -> UniResult<T, K>
where
F: FnOnce() -> S,
S: Into<Cow<'static, str>>,
K: Default;
fn kind_context_fn<F, F2, S>(self, kind: F, context: F2) -> UniResult<T, K>
where
F: FnOnce() -> K,
F2: FnOnce() -> S,
S: Into<Cow<'static, str>>;
fn kind_default(self) -> UniResult<T, K>
where
K: Default;
}
impl<K, T, E: UniStdError> ResultContext<K, T> for Result<T, E> {
fn kind(self, kind: K) -> UniResult<T, K> {
self.map_err(|err| err.kind(kind))
}
fn kind_default_context(self, context: impl Into<Cow<'static, str>>) -> UniResult<T, K>
where
K: Default,
{
self.map_err(|err| err.kind_default_context(context))
}
fn kind_context(self, kind: K, context: impl Into<Cow<'static, str>>) -> UniResult<T, K> {
self.map_err(|err| err.kind_context(kind, context))
}
fn kind_fn<F>(self, kind: F) -> UniResult<T, K>
where
F: FnOnce() -> K,
{
self.map_err(|err| err.kind(kind()))
}
fn kind_default_context_fn<F, S>(self, context: F) -> UniResult<T, K>
where
F: FnOnce() -> S,
S: Into<Cow<'static, str>>,
K: Default,
{
self.map_err(|err| err.kind_default_context(context()))
}
fn kind_context_fn<F, F2, S>(self, kind: F, context: F2) -> UniResult<T, K>
where
F: FnOnce() -> K,
F2: FnOnce() -> S,
S: Into<Cow<'static, str>>,
{
self.map_err(|err| err.kind_context(kind(), context()))
}
fn kind_default(self) -> UniResult<T, K>
where
K: Default,
{
self.map_err(|err| err.kind_default())
}
}
impl<K, T> ResultContext<K, T> for Option<T> {
fn kind(self, kind: K) -> UniResult<T, K> {
self.ok_or_else(|| UniError::from_kind(kind))
}
fn kind_default_context(self, context: impl Into<Cow<'static, str>>) -> UniResult<T, K>
where
K: Default,
{
self.ok_or_else(|| UniError::from_kind_default_context(context))
}
fn kind_context(self, kind: K, context: impl Into<Cow<'static, str>>) -> UniResult<T, K> {
self.ok_or_else(|| UniError::from_kind_context(kind, context))
}
fn kind_fn<F>(self, kind: F) -> UniResult<T, K>
where
F: FnOnce() -> K,
{
self.ok_or_else(|| UniError::from_kind(kind()))
}
fn kind_default_context_fn<F, S>(self, context: F) -> UniResult<T, K>
where
F: FnOnce() -> S,
S: Into<Cow<'static, str>>,
K: Default,
{
self.ok_or_else(|| UniError::from_kind_default_context(context()))
}
fn kind_context_fn<F, F2, S>(self, kind: F, context: F2) -> UniResult<T, K>
where
F: FnOnce() -> K,
F2: FnOnce() -> S,
S: Into<Cow<'static, str>>,
{
self.ok_or_else(|| UniError::from_kind_context(kind(), context()))
}
fn kind_default(self) -> UniResult<T, K>
where
K: Default,
{
self.ok_or_else(|| UniError::from_kind(Default::default()))
}
}
impl<K: UniKind, K2, T> ResultContext<K2, T> for UniResult<T, K> {
fn kind(self, kind: K2) -> UniResult<T, K2> {
self.map_err(|err| err.kind(kind))
}
fn kind_default_context(self, context: impl Into<Cow<'static, str>>) -> UniResult<T, K2>
where
K2: Default,
{
self.map_err(|err| err.kind_default_context(context))
}
fn kind_context(self, kind: K2, context: impl Into<Cow<'static, str>>) -> UniResult<T, K2> {
self.map_err(|err| err.kind_context(kind, context))
}
fn kind_fn<F>(self, kind: F) -> UniResult<T, K2>
where
F: FnOnce() -> K2,
{
self.map_err(|err| err.kind(kind()))
}
fn kind_default_context_fn<F, S>(self, context: F) -> UniResult<T, K2>
where
F: FnOnce() -> S,
S: Into<Cow<'static, str>>,
K2: Default,
{
self.map_err(|err| err.kind_default_context(context()))
}
fn kind_context_fn<F, F2, S>(self, kind: F, context: F2) -> UniResult<T, K2>
where
F: FnOnce() -> K2,
F2: FnOnce() -> S,
S: Into<Cow<'static, str>>,
{
self.map_err(|err| err.kind_context(kind(), context()))
}
fn kind_default(self) -> UniResult<T, K2>
where
K2: Default,
{
self.map_err(|err| err.kind_default())
}
}
impl<K2, T> ResultContext<K2, T> for UniResult<T, dyn UniKind> {
fn kind(self, kind: K2) -> UniResult<T, K2> {
self.map_err(|err| err.kind(kind))
}
fn kind_default_context(self, context: impl Into<Cow<'static, str>>) -> UniResult<T, K2>
where
K2: Default,
{
self.map_err(|err| err.kind_default_context(context))
}
fn kind_context(self, kind: K2, context: impl Into<Cow<'static, str>>) -> UniResult<T, K2> {
self.map_err(|err| err.kind_context(kind, context))
}
fn kind_fn<F>(self, kind: F) -> UniResult<T, K2>
where
F: FnOnce() -> K2,
{
self.map_err(|err| err.kind(kind()))
}
fn kind_default_context_fn<F, S>(self, context: F) -> UniResult<T, K2>
where
F: FnOnce() -> S,
S: Into<Cow<'static, str>>,
K2: Default,
{
self.map_err(|err| err.kind_default_context(context()))
}
fn kind_context_fn<F, F2, S>(self, kind: F, context: F2) -> UniResult<T, K2>
where
F: FnOnce() -> K2,
F2: FnOnce() -> S,
S: Into<Cow<'static, str>>,
{
self.map_err(|err| err.kind_context(kind(), context()))
}
fn kind_default(self) -> UniResult<T, K2>
where
K2: Default,
{
self.map_err(|err| err.kind_default())
}
}
impl<C: 'static, K2, T> ResultContext<K2, T> for UniResult<T, dyn UniKindCode<Code = C>> {
fn kind(self, kind: K2) -> UniResult<T, K2> {
self.map_err(|err| err.kind(kind))
}
fn kind_default_context(self, context: impl Into<Cow<'static, str>>) -> UniResult<T, K2>
where
K2: Default,
{
self.map_err(|err| err.kind_default_context(context))
}
fn kind_context(self, kind: K2, context: impl Into<Cow<'static, str>>) -> UniResult<T, K2> {
self.map_err(|err| err.kind_context(kind, context))
}
fn kind_fn<F>(self, kind: F) -> UniResult<T, K2>
where
F: FnOnce() -> K2,
{
self.map_err(|err| err.kind(kind()))
}
fn kind_default_context_fn<F, S>(self, context: F) -> UniResult<T, K2>
where
F: FnOnce() -> S,
S: Into<Cow<'static, str>>,
K2: Default,
{
self.map_err(|err| err.kind_default_context(context()))
}
fn kind_context_fn<F, F2, S>(self, kind: F, context: F2) -> UniResult<T, K2>
where
F: FnOnce() -> K2,
F2: FnOnce() -> S,
S: Into<Cow<'static, str>>,
{
self.map_err(|err| err.kind_context(kind(), context()))
}
fn kind_default(self) -> UniResult<T, K2>
where
K2: Default,
{
self.map_err(|err| err.kind_default())
}
}
impl<C: 'static, C2: 'static, K2, T> ResultContext<K2, T>
for UniResult<T, dyn UniKindCodes<Code = C, Code2 = C2>>
{
fn kind(self, kind: K2) -> UniResult<T, K2> {
self.map_err(|err| err.kind(kind))
}
fn kind_default_context(self, context: impl Into<Cow<'static, str>>) -> UniResult<T, K2>
where
K2: Default,
{
self.map_err(|err| err.kind_default_context(context))
}
fn kind_context(self, kind: K2, context: impl Into<Cow<'static, str>>) -> UniResult<T, K2> {
self.map_err(|err| err.kind_context(kind, context))
}
fn kind_fn<F>(self, kind: F) -> UniResult<T, K2>
where
F: FnOnce() -> K2,
{
self.map_err(|err| err.kind(kind()))
}
fn kind_default_context_fn<F, S>(self, context: F) -> UniResult<T, K2>
where
F: FnOnce() -> S,
S: Into<Cow<'static, str>>,
K2: Default,
{
self.map_err(|err| err.kind_default_context(context()))
}
fn kind_context_fn<F, F2, S>(self, kind: F, context: F2) -> UniResult<T, K2>
where
F: FnOnce() -> K2,
F2: FnOnce() -> S,
S: Into<Cow<'static, str>>,
{
self.map_err(|err| err.kind_context(kind(), context()))
}
fn kind_default(self) -> UniResult<T, K2>
where
K2: Default,
{
self.map_err(|err| err.kind_default())
}
}
pub trait UniResultContextModify<K: ?Sized + 'static, T> {
fn add_context(self, context: impl Into<Cow<'static, str>>) -> UniResult<T, K>;
fn add_context_fn<F, S>(self, context: F) -> UniResult<T, K>
where
F: FnOnce() -> S,
S: Into<Cow<'static, str>>;
}
impl<K: ?Sized + 'static, T> UniResultContextModify<K, T> for UniResult<T, K> {
fn add_context(self, context: impl Into<Cow<'static, str>>) -> UniResult<T, K> {
self.map_err(|err| err.add_context(context))
}
fn add_context_fn<F, S>(self, context: F) -> UniResult<T, K>
where
F: FnOnce() -> S,
S: Into<Cow<'static, str>>,
{
self.map_err(|err| err.add_context(context()))
}
}
pub trait UniResultContext<K, K2, T> {
fn kind_map<F>(self, f: F) -> UniResult<T, K2>
where
F: FnOnce(UniError<K>, K) -> UniError<K2>,
K: Clone;
fn kind_into(self) -> UniResult<T, K2>
where
K: Clone + Into<K2>;
fn kind_into_context(self, context: impl Into<Cow<'static, str>>) -> UniResult<T, K2>
where
K: Clone + Into<K2>;
fn kind_into_context_fn<F, S>(self, context: F) -> UniResult<T, K2>
where
F: FnOnce() -> S,
S: Into<Cow<'static, str>>,
K: Clone + Into<K2>;
}
impl<K: UniKind, K2, T> UniResultContext<K, K2, T> for UniResult<T, K> {
fn kind_map<F>(self, f: F) -> UniResult<T, K2>
where
F: FnOnce(UniError<K>, K) -> UniError<K2>,
K: Clone,
{
self.map_err(|err| err.kind_map(f))
}
fn kind_into(self) -> UniResult<T, K2>
where
K: Clone + Into<K2>,
{
self.map_err(|err| err.kind_into())
}
fn kind_into_context(self, context: impl Into<Cow<'static, str>>) -> UniResult<T, K2>
where
K: Clone + Into<K2>,
{
self.map_err(|err| err.kind_into_context(context))
}
fn kind_into_context_fn<F, S>(self, context: F) -> UniResult<T, K2>
where
F: FnOnce() -> S,
S: Into<Cow<'static, str>>,
K: Clone + Into<K2>,
{
self.map_err(|err| err.kind_into_context(context()))
}
}
pub trait ErrorContextDisplay<K> {
fn kind_disp(self, kind: K) -> UniError<K>;
fn kind_default_context_disp(self, context: impl Into<Cow<'static, str>>) -> UniError<K>
where
K: Default;
fn kind_context_disp(self, kind: K, context: impl Into<Cow<'static, str>>) -> UniError<K>;
fn kind_default_disp(self) -> UniError<K>
where
K: Default;
}
impl<K, D: UniDisplay> ErrorContextDisplay<K> for D {
fn kind_disp(self, kind: K) -> UniError<K> {
UniError::new(kind, None, Some(CauseInner::from_display(self)))
}
fn kind_default_context_disp(self, context: impl Into<Cow<'static, str>>) -> UniError<K>
where
K: Default,
{
UniError::new(
Default::default(),
Some(context.into()),
Some(CauseInner::from_display(self)),
)
}
fn kind_context_disp(self, kind: K, context: impl Into<Cow<'static, str>>) -> UniError<K> {
UniError::new(
kind,
Some(context.into()),
Some(CauseInner::from_display(self)),
)
}
fn kind_default_disp(self) -> UniError<K>
where
K: Default,
{
UniError::new(
Default::default(),
None,
Some(CauseInner::from_display(self)),
)
}
}
pub trait ResultContextDisplay<K, T> {
fn kind_disp(self, kind: K) -> UniResult<T, K>;
fn kind_default_context_disp(self, context: impl Into<Cow<'static, str>>) -> UniResult<T, K>
where
K: Default;
fn kind_context_disp(self, kind: K, context: impl Into<Cow<'static, str>>) -> UniResult<T, K>;
fn kind_disp_fn<F>(self, kind: F) -> UniResult<T, K>
where
F: FnOnce() -> K;
fn kind_default_context_disp_fn<F, S>(self, context: F) -> UniResult<T, K>
where
F: FnOnce() -> S,
S: Into<Cow<'static, str>>,
K: Default;
fn kind_context_disp_fn<F, F2, S>(self, kind: F, context: F2) -> UniResult<T, K>
where
F: FnOnce() -> K,
F2: FnOnce() -> S,
S: Into<Cow<'static, str>>;
fn kind_default_disp(self) -> UniResult<T, K>
where
K: Default;
}
impl<K, T, D: UniDisplay> ResultContextDisplay<K, T> for Result<T, D> {
fn kind_default_context_disp(self, context: impl Into<Cow<'static, str>>) -> UniResult<T, K>
where
K: Default,
{
self.map_err(|err| err.kind_default_context_disp(context))
}
fn kind_disp(self, kind: K) -> UniResult<T, K> {
self.map_err(|err| err.kind_disp(kind))
}
fn kind_context_disp(self, kind: K, context: impl Into<Cow<'static, str>>) -> UniResult<T, K> {
self.map_err(|err| err.kind_context_disp(kind, context))
}
fn kind_disp_fn<F>(self, kind: F) -> UniResult<T, K>
where
F: FnOnce() -> K,
{
self.map_err(|err| err.kind_disp(kind()))
}
fn kind_default_context_disp_fn<F, S>(self, context: F) -> UniResult<T, K>
where
F: FnOnce() -> S,
S: Into<Cow<'static, str>>,
K: Default,
{
self.map_err(|err| err.kind_default_context_disp(context()))
}
fn kind_context_disp_fn<F, F2, S>(self, kind: F, context: F2) -> UniResult<T, K>
where
F: FnOnce() -> K,
F2: FnOnce() -> S,
S: Into<Cow<'static, str>>,
{
self.map_err(|err| err.kind_context_disp(kind(), context()))
}
fn kind_default_disp(self) -> UniResult<T, K>
where
K: Default,
{
self.map_err(|err| err.kind_default_disp())
}
}