#![no_std]
#![allow(clippy::type_complexity)]
extern crate alloc;
#[cfg(feature = "backtrace")]
extern crate std;
mod backtrace;
mod ptr;
mod raw;
mod render;
mod rtti;
#[doc(hidden)]
pub mod macros;
pub mod context;
pub mod nae;
pub mod payload;
pub mod state;
use alloc::boxed::Box;
use core::{
error,
fmt::{self, Debug, Display},
marker::PhantomData,
ops::Deref,
result,
};
use crate::{
context::{Context, Literal},
nae::Nae,
payload::{Immediate, PayloadFn},
raw::RawError,
state::{State, Stateless, Vacant},
};
pub type Result<T> = result::Result<T, Error>;
#[repr(transparent)]
pub struct Error<S = Stateless>(RawError<S::Repr>)
where
S: State + ?Sized;
impl Error {
pub fn with_error<E>(
err: E,
) -> Builder<E, Stateless, Immediate<payload::Empty>, context::Blank> {
Builder {
err,
context: PhantomData,
state: None,
payload_fn: Immediate(payload::Empty::new()),
}
}
pub fn with_state<S>(state: S) -> Builder<Nae, S, Immediate<payload::Empty>, context::Blank>
where
S: State,
{
Builder {
err: Nae::new(),
context: PhantomData,
state: Some(state.into_repr()),
payload_fn: Immediate(payload::Empty::new()),
}
}
pub fn with_payload<P>(payload: P) -> Builder<Nae, Stateless, Immediate<P>, context::Blank>
where
P: Display + Send + Sync + 'static,
{
Builder {
err: Nae::new(),
context: PhantomData,
state: None,
payload_fn: Immediate(payload),
}
}
pub fn with_payload_fn<F>(payload_fn: F) -> Builder<Nae, Stateless, F, context::Blank>
where
F: PayloadFn,
{
Builder {
err: Nae::new(),
context: PhantomData,
state: None,
payload_fn,
}
}
pub fn with_context<L>(_ty: L) -> Builder<Nae, Stateless, Immediate<payload::Empty>, L>
where
L: Context,
{
Self::with_context_ty::<L>()
}
pub fn with_context_ty<L>() -> Builder<Nae, Stateless, Immediate<payload::Empty>, L> {
Builder {
err: Nae::new(),
context: PhantomData,
state: None,
payload_fn: Immediate(payload::Empty::new()),
}
}
pub fn into_parts<P, E>(self) -> (Option<&'static str>, Option<P>, Option<E>)
where
E: 'static,
P: 'static,
{
let (_state, context, payload, source) = self.0.into_parts::<P, E>();
(context, payload, source)
}
pub fn stateless(self) -> Self {
self
}
}
impl<S> Error<S>
where
S: State + ?Sized,
{
pub fn erase(self) -> impl error::Error + Send + Sync + 'static {
ImplError::<S>(self.0)
}
pub fn erase_ref(&self) -> &(impl error::Error + Send + Sync + 'static) {
&self.0
}
pub fn from_error<E>(err: E) -> Self
where
E: error::Error + Send + Sync + 'static,
{
err.into()
}
pub fn from_context<L>(_ty: L) -> Self
where
L: Literal,
{
Self::from_context_ty::<L>()
}
pub fn from_context_ty<L>() -> Self
where
L: Literal,
{
if let Ok(err) =
rtti::concretize::<Error<Stateless>, Error<S>>(Error(RawError::new_const::<L>()))
{
return err;
}
Self(RawError::new_boxed::<_, _, context::Blank>(
None,
Nae::new(),
payload::Empty::new(),
))
}
pub fn from_payload<P>(payload: P) -> Self
where
P: Display + Send + Sync + 'static,
{
Self(RawError::new_boxed::<_, P, context::Blank>(
None,
Nae::new(),
payload,
))
}
pub fn from_boxed(value: Box<dyn error::Error + Send + Sync + 'static>) -> Self {
struct BoxError(Box<dyn error::Error + Send + Sync + 'static>);
impl Debug for BoxError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
Debug::fmt(&*self.0, f)
}
}
impl Display for BoxError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
Display::fmt(&*self.0, f)
}
}
impl error::Error for BoxError {
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
self.0.source()
}
}
Self(RawError::new_boxed::<_, _, context::Blank>(
None,
BoxError(value),
payload::Empty::new(),
))
}
pub fn has_state(&self) -> bool {
self.0.state().is_some()
}
pub fn try_into_stateless(self) -> result::Result<Error, Self> {
match self.0.extract_state() {
Err(err) => Ok(Error(err)),
Ok((state, Some(vac))) => match vac.try_into_stateless() {
Ok(err) => Ok(Error(err)),
Err(vac) => Err(Error(
vac.try_with_state(state)
.expect("try_with_state will not fail with correct state"),
)),
},
Ok((state, None)) => Err(Error(RawError::new_inline_or_boxed(state))),
}
}
pub fn context(&self) -> Option<&(dyn Display + Send + Sync + 'static)> {
self.0.context()
}
pub fn payload(&self) -> Option<&(dyn Display + Send + Sync + 'static)> {
self.0.payload()
}
pub fn has_source_of<E>(&self) -> bool
where
E: error::Error + 'static,
{
self.0.downcast_source_ref::<E>().is_some()
}
pub fn source(&self) -> Option<&(dyn error::Error + 'static)> {
self.0.source().map(|v| v as _)
}
pub fn downcast_source_ref<E>(&self) -> Option<&E>
where
E: error::Error + 'static,
{
self.0.downcast_source_ref::<E>()
}
pub fn downcast_source_mut<E>(&mut self) -> Option<&mut E>
where
E: error::Error + 'static,
{
self.0.downcast_source_mut::<E>()
}
pub fn has_payload_of<P>(&self) -> bool
where
P: 'static,
{
self.0.downcast_payload_ref::<P>().is_some()
}
pub fn downcast_payload_ref<P>(&self) -> Option<&P>
where
P: 'static,
{
self.0.downcast_payload_ref::<P>()
}
pub fn downcast_payload_mut<P>(&mut self) -> Option<&mut P>
where
P: 'static,
{
self.0.downcast_payload_mut::<P>()
}
pub fn into_source(self) -> Option<Box<dyn error::Error + Send + Sync + 'static>> {
self.0.into_source()
}
pub fn chain(&self) -> impl Iterator<Item = &(dyn error::Error + 'static)> {
self.0.chain()
}
pub fn with_phantom_state<S2>(self) -> Error<S2>
where
S2: State + ?Sized,
{
let Err(err) = match_else!(rtti::concretize::<_, Error<S2>>(self), Ok(err) => {
return err;
});
let Err(err) = match_else!(err.try_into_stateless(), Ok(err) => {
return Error(err.0.with_phantom_state());
});
Error(RawError::new_boxed::<_, _, context::Blank>(
None,
err.erase(),
payload::Empty::new(),
))
}
#[cfg_attr(docsrs, doc(cfg(feature = "backtrace")))]
#[cfg(feature = "backtrace")]
pub fn backtrace(&self) -> Option<&std::backtrace::Backtrace> {
self.0.backtrace()
}
}
impl<S> Error<S>
where
S: State,
{
pub fn from_state(state: S) -> Self {
Error(RawError::new_inline_or_boxed(S::into_repr(state)))
}
pub fn state(&self) -> Option<&S> {
self.0.state().map(S::from_repr_ref)
}
pub fn into_parts<P, E>(self) -> (Option<S>, Option<&'static str>, Option<P>, Option<E>)
where
E: 'static,
P: 'static,
{
let (state, context, payload, error) = self.0.into_parts::<P, E>();
(state.map(S::from_repr), context, payload, error)
}
pub fn extract_state(self) -> result::Result<(S, Vacant<S>), Error> {
match self.0.extract_state() {
Ok((s, o)) => Ok((S::from_repr(s), Vacant::new(o))),
Err(e) => Err(Error(e)),
}
}
pub fn map_state<F, S2>(self, f: F) -> Error<S2>
where
F: FnOnce(S) -> S2,
S2: State,
{
let Ok((state, vacant)) = match_else!(self.extract_state(), Err(err) => {
return err.with_phantom_state();
});
let state = f(state);
let Err(vacant) = match_else!(rtti::concretize::<_, Vacant<S2>>(vacant), Ok(vacant) => {
return vacant.with_state(state);
});
match vacant.try_into_stateless() {
Ok(err) => Error(RawError::new_boxed::<_, _, context::Blank>(
Some(S2::into_repr(state)),
err.erase(),
payload::Empty::new(),
)),
Err(_) => Error(RawError::new_inline_or_boxed(S2::into_repr(state))),
}
}
pub fn lift_state<S2>(self) -> Error<S2>
where
S2: From<S> + State,
{
self.map_state(S2::from)
}
}
impl<S> Deref for Error<S>
where
S: State + ?Sized,
{
type Target = dyn error::Error + Send + Sync + 'static;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<E, S> From<E> for Error<S>
where
E: error::Error + Send + Sync + 'static,
S: State + ?Sized,
{
fn from(err: E) -> Self {
let Err(err) = match_else!(rtti::concretize::<E, ImplError<S>>(err),
Ok(err_unit) => return Error(err_unit.0),
);
let Err(err) = match_else!(rtti::concretize::<E, ImplError<Stateless>>(err),
Ok(err_unit) => return Error(err_unit.0.with_phantom_state()),
);
Error(RawError::new_boxed::<_, _, context::Blank>(
None,
err,
payload::Empty::new(),
))
}
}
impl<S> From<Error> for Error<S>
where
S: State,
{
fn from(value: Error) -> Self {
value.with_phantom_state()
}
}
impl<S> From<Error<S>> for Box<dyn error::Error + 'static>
where
S: State + ?Sized,
{
fn from(value: Error<S>) -> Self {
value.0.into_boxed_error()
}
}
impl<S> From<Error<S>> for Box<dyn error::Error + Send + 'static>
where
S: State + ?Sized,
{
fn from(value: Error<S>) -> Self {
value.0.into_boxed_error()
}
}
impl<S> From<Error<S>> for Box<dyn error::Error + Sync + 'static>
where
S: State + ?Sized,
{
fn from(value: Error<S>) -> Self {
value.0.into_boxed_error()
}
}
impl<S> From<Error<S>> for Box<dyn error::Error + Send + Sync + 'static>
where
S: State + ?Sized,
{
fn from(value: Error<S>) -> Self {
value.0.into_boxed_error()
}
}
impl<S> Debug for Error<S>
where
S: State + ?Sized,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
Debug::fmt(&self.0, f)
}
}
impl<S> Display for Error<S>
where
S: State + ?Sized,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
Display::fmt(&self.0, f)
}
}
#[repr(transparent)]
struct ImplError<S = Stateless>(RawError<S::Repr>)
where
S: State + ?Sized;
impl<S> Debug for ImplError<S>
where
S: State + ?Sized,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
Debug::fmt(&self.0, f)
}
}
impl<S> Display for ImplError<S>
where
S: State + ?Sized,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
Display::fmt(&self.0, f)
}
}
impl<S> error::Error for ImplError<S>
where
S: State + ?Sized,
{
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
self.0.source().map(|s| s as _)
}
}
#[derive(Debug)]
pub struct Builder<E, S, F, L>
where
F: PayloadFn,
S: State + ?Sized,
L: ?Sized,
{
err: E,
state: Option<S::Repr>,
payload_fn: F,
context: PhantomData<L>,
}
impl<E, S, F, L> From<Builder<E, S, F, L>> for Error<S>
where
F: PayloadFn,
E: error::Error + Send + Sync + 'static,
S: State + ?Sized,
L: Context + ?Sized,
{
fn from(value: Builder<E, S, F, L>) -> Self {
let has_state = !rtti::is_same_ty::<S, Stateless>();
let has_context = !rtti::is_same_ty::<L, context::Blank>();
let has_error = !rtti::is_same_ty::<E, Nae>();
let has_payload = !rtti::is_same_ty::<F::Output, payload::Empty>();
match (has_state, has_context, has_error, has_payload) {
(false, false, false, false) => unreachable!(),
(false, false, true, false) => value.err.into(),
(true, false, false, false) => {
Error::<S>(RawError::new_inline_or_boxed(match value.state {
Some(state) => state,
None => unreachable!(), }))
}
(false, true, false, false) => {
let Ok(body) = match_else!(rtti::concretize::<_, RawError<S::Repr>>(RawError::new_const::<L>()),
Err(_) => unreachable!(),
);
Error(body)
}
_ => Error::<S>(RawError::new_boxed::<_, _, L>(
value.state,
value.err,
value.payload_fn.call(),
)),
}
}
}
impl<E, S, F, L> From<Builder<E, Stateless, F, L>> for Error<S>
where
F: PayloadFn,
E: error::Error + Send + Sync + 'static,
S: State,
L: Context + ?Sized,
{
fn from(value: Builder<E, Stateless, F, L>) -> Self {
let has_context = !rtti::is_same_ty::<L, context::Blank>();
let has_error = !rtti::is_same_ty::<E, Nae>();
let has_payload = !rtti::is_same_ty::<F::Output, payload::Empty>();
match (has_context, has_error, has_payload) {
(false, false, false) => unreachable!(),
(false, true, false) => value.err.into(),
(true, false, false) => {
Error::<Stateless>(RawError::new_const::<L>()).with_phantom_state()
}
_ => Error(RawError::new_boxed::<_, _, L>(
None,
value.err,
value.payload_fn.call(),
)),
}
}
}
impl<S1, S, F, L> From<Builder<Error<S1>, S, F, L>> for Error<S>
where
S1: State + ?Sized,
F: PayloadFn,
S: State + ?Sized,
L: Context + ?Sized,
{
fn from(value: Builder<Error<S1>, S, F, L>) -> Self {
let has_state = !rtti::is_same_ty::<S, Stateless>();
let has_context = !rtti::is_same_ty::<L, context::Blank>();
let has_payload = !rtti::is_same_ty::<F::Output, payload::Empty>();
match (has_state, has_context, has_payload) {
(false, false, false) => value.err.with_phantom_state(),
_ => Error(RawError::new_boxed::<_, _, L>(
value.state,
value.err.erase(),
value.payload_fn.call(),
)),
}
}
}
impl<S1, S, F, L> From<Builder<Error<S1>, Stateless, F, L>> for Error<S>
where
S1: State + ?Sized,
F: PayloadFn,
S: State,
L: Context + ?Sized,
{
fn from(value: Builder<Error<S1>, Stateless, F, L>) -> Self {
let has_context = !rtti::is_same_ty::<L, context::Blank>();
let has_payload = !rtti::is_same_ty::<F::Output, payload::Empty>();
match (has_context, has_payload) {
(false, false) => value.err.with_phantom_state(),
_ => Error(RawError::new_boxed::<_, _, L>(
None,
value.err.erase(),
value.payload_fn.call(),
)),
}
}
}
pub trait StateExt {
type T;
type S: State;
type Result<T, E>;
fn extract_state(
self,
) -> result::Result<Self::Result<Self::T, (Self::S, Vacant<Self::S>)>, Error>
where
Self::S: Sized;
fn map_state<F, S>(self, f: F) -> Self::Result<Self::T, Error<S>>
where
F: FnOnce(Self::S) -> S,
S: State;
fn lift_state<S>(self) -> Self::Result<Self::T, Error<S>>
where
S: State,
S: From<Self::S>,
Self: Sized,
{
self.map_state(S::from)
}
}
impl<S1> StateExt for Error<S1>
where
S1: State,
{
type T = ();
type S = S1;
type Result<T, E> = E;
fn extract_state(
self,
) -> result::Result<Self::Result<Self::T, (Self::S, Vacant<Self::S>)>, Error>
where
Self::S: Sized,
{
self.extract_state()
}
fn map_state<F, S>(self, f: F) -> Self::Result<Self::T, Error<S>>
where
F: FnOnce(Self::S) -> S,
S: State,
{
self.map_state(f)
}
}
impl<T1, S> StateExt for result::Result<T1, Error<S>>
where
S: State,
{
type T = T1;
type S = S;
type Result<T, E> = result::Result<T, E>;
fn extract_state(
self,
) -> result::Result<Self::Result<Self::T, (Self::S, Vacant<Self::S>)>, Error>
where
Self::S: Sized,
{
match self {
Ok(v) => Ok(Ok(v)),
Err(err) => err.build_error().extract_state().map(|err| Err(err)),
}
}
fn map_state<F, S2>(self, f: F) -> Self::Result<Self::T, Error<S2>>
where
F: FnOnce(Self::S) -> S2,
S2: State,
{
self.map_err(|err| err.map_state(f))
}
}
impl<E1, S, F, L> StateExt for Builder<E1, S, F, L>
where
E1: error::Error + Send + Sync + 'static,
F: PayloadFn,
S: State,
L: Context + ?Sized,
{
type T = ();
type Result<T, E> = E;
type S = S;
fn extract_state(
self,
) -> result::Result<Self::Result<Self::T, (Self::S, Vacant<Self::S>)>, Error>
where
Self::S: Sized,
{
self.build_error().extract_state()
}
fn map_state<M, S2>(self, f: M) -> Self::Result<Self::T, Error<S2>>
where
M: FnOnce(Self::S) -> S2,
S2: State,
{
self.build_error().map_state(f)
}
}
impl<S1, S, F, L> StateExt for Builder<Error<S1>, S, F, L>
where
S1: State + ?Sized,
F: PayloadFn,
S: State,
L: Context + ?Sized,
{
type T = ();
type S = S;
type Result<T, E> = E;
fn extract_state(
self,
) -> result::Result<Self::Result<Self::T, (Self::S, Vacant<Self::S>)>, Error>
where
Self::S: Sized,
{
self.build_error().extract_state()
}
fn map_state<M, S2>(self, f: M) -> Self::Result<Self::T, Error<S2>>
where
M: FnOnce(Self::S) -> S2,
S2: State,
{
self.build_error().map_state(f)
}
}
impl<T1, E1, S, F, L> StateExt for result::Result<T1, Builder<E1, S, F, L>>
where
E1: error::Error + Send + Sync + 'static,
F: PayloadFn,
S: State,
L: Context + ?Sized,
{
type T = T1;
type S = S;
type Result<T, E> = result::Result<T, E>;
fn extract_state(
self,
) -> result::Result<Self::Result<Self::T, (Self::S, Vacant<Self::S>)>, Error>
where
Self::S: Sized,
{
match self {
Ok(v) => Ok(Ok(v)),
Err(err) => err.build_error().extract_state().map(|err| Err(err)),
}
}
fn map_state<M, S2>(self, f: M) -> Self::Result<Self::T, Error<S2>>
where
M: FnOnce(Self::S) -> S2,
S2: State,
{
self.map_err(|err| err.map_state(f))
}
}
impl<T1, S1, S, F, L> StateExt for result::Result<T1, Builder<Error<S1>, S, F, L>>
where
S1: State + ?Sized,
F: PayloadFn,
S: State,
L: Context + ?Sized,
{
type T = T1;
type S = S;
type Result<T, E> = result::Result<T, E>;
fn extract_state(
self,
) -> result::Result<Self::Result<Self::T, (Self::S, Vacant<Self::S>)>, Error>
where
Self::S: Sized,
{
match self {
Ok(v) => Ok(Ok(v)),
Err(err) => err.build_error().extract_state().map(|err| Err(err)),
}
}
fn map_state<M, S2>(self, f: M) -> Self::Result<Self::T, Error<S2>>
where
M: FnOnce(Self::S) -> S2,
S2: State,
{
self.map_err(|err| err.map_state(f))
}
}
pub trait BuilderExt: Sized {
type Result<E>;
type E;
type S: State + ?Sized;
type F: PayloadFn;
type L: Literal + ?Sized;
fn with_context_ty<L>(self) -> Self::Result<Builder<Self::E, Self::S, Self::F, L>>
where
L: Context;
fn with_context<L>(self, _ty: L) -> Self::Result<Builder<Self::E, Self::S, Self::F, L>>
where
L: Context,
{
self.with_context_ty::<L>()
}
fn with_state<S>(self, state: S) -> Self::Result<Builder<Self::E, S, Self::F, Self::L>>
where
S: State + Sized;
fn with_payload_fn<F>(
self,
payload_fn: F,
) -> Self::Result<Builder<Self::E, Self::S, F, Self::L>>
where
F: PayloadFn;
fn with_payload<P>(
self,
payload: P,
) -> Self::Result<Builder<Self::E, Self::S, Immediate<P>, Self::L>>
where
P: Display + Send + Sync + 'static,
{
self.with_payload_fn(Immediate(payload))
}
}
impl<T, E1> BuilderExt for result::Result<T, E1>
where
E1: error::Error + Send + Sync + 'static,
{
type Result<E> = result::Result<T, E>;
type E = E1;
type S = Stateless;
type F = Immediate<payload::Empty>;
type L = context::Blank;
fn with_context_ty<L>(self) -> Self::Result<Builder<Self::E, Self::S, Self::F, L>>
where
L: Context,
{
self.map_err(|err| Builder {
err,
context: PhantomData,
state: None,
payload_fn: Immediate(payload::Empty::new()),
})
}
fn with_state<S>(self, state: S) -> Self::Result<Builder<Self::E, S, Self::F, Self::L>>
where
S: State + Sized,
{
self.map_err(|err| Builder {
err,
context: PhantomData,
state: Some(state.into_repr()),
payload_fn: Immediate(payload::Empty::new()),
})
}
fn with_payload_fn<F>(
self,
payload_fn: F,
) -> Self::Result<Builder<Self::E, Self::S, F, Self::L>>
where
F: PayloadFn,
{
self.map_err(|err| Builder {
err,
context: PhantomData,
state: None,
payload_fn,
})
}
}
impl<T, S1> BuilderExt for result::Result<T, Error<S1>>
where
S1: State + ?Sized,
{
type Result<E> = result::Result<T, E>;
type E = Error<S1>;
type S = Stateless;
type F = Immediate<payload::Empty>;
type L = context::Blank;
fn with_context_ty<L>(self) -> Self::Result<Builder<Self::E, Self::S, Self::F, L>>
where
L: Context,
{
self.map_err(|err| Builder {
err,
context: PhantomData,
state: None,
payload_fn: Immediate(payload::Empty::new()),
})
}
fn with_state<S>(self, state: S) -> Self::Result<Builder<Self::E, S, Self::F, Self::L>>
where
S: State,
{
self.map_err(|err| Builder {
err,
context: PhantomData,
state: Some(state.into_repr()),
payload_fn: Immediate(payload::Empty::new()),
})
}
fn with_payload_fn<F>(
self,
payload_fn: F,
) -> Self::Result<Builder<Self::E, Self::S, F, Self::L>>
where
F: PayloadFn,
{
self.map_err(|err| Builder {
err,
context: PhantomData,
state: None,
payload_fn,
})
}
}
impl<E1, S1, F1, L1> BuilderExt for Builder<E1, S1, F1, L1>
where
F1: PayloadFn,
S1: State + ?Sized,
L1: Literal + ?Sized,
{
type Result<E> = E;
type E = E1;
type S = S1;
type F = F1;
type L = L1;
fn with_context_ty<L>(self) -> Self::Result<Builder<Self::E, Self::S, Self::F, L>>
where
L: Context,
{
Builder {
err: self.err,
context: PhantomData,
state: self.state,
payload_fn: self.payload_fn,
}
}
fn with_state<S>(self, state: S) -> Self::Result<Builder<Self::E, S, Self::F, Self::L>>
where
S: State,
{
Builder {
state: Some(state.into_repr()),
err: self.err,
context: self.context,
payload_fn: self.payload_fn,
}
}
fn with_payload_fn<F>(
self,
payload_fn: F,
) -> Self::Result<Builder<Self::E, Self::S, F, Self::L>>
where
F: PayloadFn,
{
Builder {
err: self.err,
context: self.context,
state: self.state,
payload_fn,
}
}
}
impl<T, E1, S1, F1, L1> BuilderExt for result::Result<T, Builder<E1, S1, F1, L1>>
where
F1: PayloadFn,
S1: State + ?Sized,
L1: Literal + ?Sized,
{
type Result<E> = result::Result<T, E>;
type E = E1;
type S = S1;
type F = F1;
type L = L1;
fn with_context_ty<L>(self) -> Self::Result<Builder<Self::E, Self::S, Self::F, L>>
where
L: Context,
{
self.map_err(|err| Builder {
err: err.err,
context: PhantomData,
state: err.state,
payload_fn: err.payload_fn,
})
}
fn with_state<S>(self, state: S) -> Self::Result<Builder<Self::E, S, Self::F, Self::L>>
where
S: State,
{
self.map_err(|err| Builder {
state: Some(state.into_repr()),
err: err.err,
context: err.context,
payload_fn: err.payload_fn,
})
}
fn with_payload_fn<F>(
self,
payload_fn: F,
) -> Self::Result<Builder<Self::E, Self::S, F, Self::L>>
where
F: PayloadFn,
{
self.map_err(|err| Builder {
err: err.err,
context: err.context,
state: err.state,
payload_fn,
})
}
}
impl<T> BuilderExt for Option<T> {
type Result<E> = result::Result<T, E>;
type E = Nae;
type S = Stateless;
type F = Immediate<payload::Empty>;
type L = context::Blank;
fn with_context_ty<L>(self) -> Self::Result<Builder<Self::E, Self::S, Self::F, L>>
where
L: Context,
{
self.ok_or(Builder {
err: Nae::new(),
context: PhantomData,
state: None,
payload_fn: Immediate(payload::Empty::new()),
})
}
fn with_state<S>(self, state: S) -> Self::Result<Builder<Self::E, S, Self::F, Self::L>>
where
S: State,
{
self.ok_or(Builder {
state: Some(state.into_repr()),
err: Nae::new(),
context: PhantomData,
payload_fn: Immediate(payload::Empty::new()),
})
}
fn with_payload_fn<F>(
self,
payload_fn: F,
) -> Self::Result<Builder<Self::E, Self::S, F, Self::L>>
where
F: PayloadFn,
{
self.ok_or(Builder {
err: Nae::new(),
context: PhantomData,
state: None,
payload_fn,
})
}
}
pub trait ErrorExt: Sized {
type Result<E>;
type S: State + ?Sized;
fn build_error(self) -> Self::Result<Error<Self::S>>;
fn erase_error(self) -> Self::Result<impl error::Error + Send + Sync + 'static>;
}
impl<S> ErrorExt for Error<S>
where
S: State + ?Sized,
{
type Result<E> = E;
type S = S;
fn build_error(self) -> Self::Result<Error<Self::S>> {
self
}
fn erase_error(self) -> Self::Result<impl error::Error + Send + Sync + 'static> {
self.erase()
}
}
impl<E1, S, F, L> ErrorExt for Builder<E1, S, F, L>
where
E1: error::Error + Send + Sync + 'static,
F: PayloadFn,
S: State + ?Sized,
L: Context + ?Sized,
{
type Result<E> = E;
type S = S;
fn build_error(self) -> Self::Result<Error<Self::S>> {
self.into()
}
fn erase_error(self) -> Self::Result<impl error::Error + Send + Sync + 'static> {
self.build_error().erase()
}
}
impl<S1, S, F, L> ErrorExt for Builder<Error<S1>, S, F, L>
where
S1: State + ?Sized,
F: PayloadFn,
S: State + ?Sized,
L: Context + ?Sized,
{
type Result<E> = E;
type S = S;
fn build_error(self) -> Self::Result<Error<Self::S>> {
Builder {
err: self.err.erase(),
state: self.state,
payload_fn: self.payload_fn,
context: self.context,
}
.build_error()
}
fn erase_error(self) -> Self::Result<impl error::Error + Send + Sync + 'static> {
self.build_error().erase()
}
}
impl<T, E1, S, F, L> ErrorExt for result::Result<T, Builder<E1, S, F, L>>
where
E1: error::Error + Send + Sync + 'static,
F: PayloadFn,
S: State + ?Sized,
L: Context + ?Sized,
{
type Result<E> = result::Result<T, E>;
type S = S;
fn build_error(self) -> Self::Result<Error<Self::S>> {
self.map_err(Error::from)
}
fn erase_error(self) -> Self::Result<impl error::Error + Send + Sync + 'static> {
self.build_error().map_err(|err| err.erase())
}
}
impl<T, S1, S, F, L> ErrorExt for result::Result<T, Builder<Error<S1>, S, F, L>>
where
S1: State + ?Sized,
F: PayloadFn,
S: State + ?Sized,
L: Context + ?Sized,
{
type Result<E> = result::Result<T, E>;
type S = S;
fn build_error(self) -> Self::Result<Error<Self::S>> {
self.map_err(|err| {
Builder {
err: err.err.erase(),
state: err.state,
payload_fn: err.payload_fn,
context: err.context,
}
.build_error()
})
}
fn erase_error(self) -> Self::Result<impl error::Error + Send + Sync + 'static> {
self.build_error().map_err(|err| err.erase())
}
}
impl<T, E1> ErrorExt for result::Result<T, E1>
where
E1: error::Error + Send + Sync + 'static,
{
type Result<E> = result::Result<T, E>;
type S = Stateless;
fn build_error(self) -> Self::Result<Error<Self::S>> {
self.map_err(Error::from)
}
fn erase_error(self) -> Self::Result<impl error::Error + Send + Sync + 'static> {
self.build_error().map_err(|err| err.erase())
}
}
impl<T, S> ErrorExt for result::Result<T, Error<S>>
where
S: State + ?Sized,
{
type Result<E> = result::Result<T, E>;
type S = S;
fn build_error(self) -> Self::Result<Error<Self::S>> {
self
}
fn erase_error(self) -> Self::Result<impl error::Error + Send + Sync + 'static> {
self.map_err(|err| err.erase())
}
}