use crate::{Error, Exn, ExnResult, Result};
use super::impls::into_frame;
pub trait ErrorExt: std::error::Error + Send + Sync + 'static {
#[track_caller]
fn raise(self) -> Error
where
Self: Sized,
{
let mut error = Some(self);
if let Some(error) = (&mut error as &mut dyn std::any::Any).downcast_mut::<Option<Error>>() {
return error.take().expect("the error has not been consumed");
}
Exn::new(error.expect("a different error type was not taken")).into_error()
}
#[track_caller]
fn raise_typed(self) -> Exn<Self>
where
Self: Sized,
{
Exn::new(self)
}
#[track_caller]
fn and_raise<T: std::error::Error + Send + Sync + 'static>(self, context: T) -> Error
where
Self: Sized,
{
self.and_raise_typed(context).into_error()
}
#[track_caller]
fn and_raise_typed<T: std::error::Error + Send + Sync + 'static>(self, context: T) -> Exn<T>
where
Self: Sized,
{
Exn::with_cause(self, context)
}
#[track_caller]
fn raise_erased(self) -> Exn
where
Self: Sized,
{
Exn::from_boxed_frame(into_frame(self))
}
#[track_caller]
fn raise_all<T, I>(self, sources: I) -> Exn<Self>
where
Self: Sized,
T: std::error::Error + Send + Sync + 'static,
I: IntoIterator,
I::Item: Into<Exn<T>>,
{
Exn::raise_all(sources, self)
}
}
impl<T> ErrorExt for T where T: std::error::Error + Send + Sync + 'static {}
pub trait OptionExt {
type Some;
fn ok_or_raise<A, F>(self, err: F) -> Result<Self::Some>
where
A: std::error::Error + Send + Sync + 'static,
F: FnOnce() -> A;
fn ok_or_raise_typed<A, F>(self, err: F) -> ExnResult<Self::Some, A>
where
A: std::error::Error + Send + Sync + 'static,
F: FnOnce() -> A;
fn ok_or_raise_erased<A, F>(self, err: F) -> ExnResult<Self::Some>
where
A: std::error::Error + Send + Sync + 'static,
F: FnOnce() -> A;
}
impl<T> OptionExt for Option<T> {
type Some = T;
#[track_caller]
fn ok_or_raise<A, F>(self, err: F) -> Result<T>
where
A: std::error::Error + Send + Sync + 'static,
F: FnOnce() -> A,
{
match self {
Some(v) => Ok(v),
None => Err(err().raise()),
}
}
#[track_caller]
fn ok_or_raise_typed<A, F>(self, err: F) -> ExnResult<T, A>
where
A: std::error::Error + Send + Sync + 'static,
F: FnOnce() -> A,
{
match self {
Some(v) => Ok(v),
None => Err(Exn::new(err())),
}
}
#[track_caller]
fn ok_or_raise_erased<A, F>(self, err: F) -> ExnResult<T>
where
A: std::error::Error + Send + Sync + 'static,
F: FnOnce() -> A,
{
match self {
Some(v) => Ok(v),
None => Err(err().raise_erased()),
}
}
}
pub trait ResultExt {
type Success;
type Error: std::error::Error + Send + Sync + 'static;
#[track_caller]
fn or_raise<A, F>(self, err: F) -> Result<Self::Success>
where
Self: Sized,
A: std::error::Error + Send + Sync + 'static,
F: FnOnce() -> A,
{
self.or_raise_typed(err).map_err(Exn::into_error)
}
#[track_caller]
fn or_error(self) -> Result<Self::Success>;
fn or_raise_typed<A, F>(self, err: F) -> ExnResult<Self::Success, A>
where
A: std::error::Error + Send + Sync + 'static,
F: FnOnce() -> A;
fn or_erased(self) -> ExnResult<Self::Success>;
#[track_caller]
fn or_raise_erased<A, F>(self, err: F) -> ExnResult<Self::Success>
where
Self: Sized,
A: std::error::Error + Send + Sync + 'static,
F: FnOnce() -> A,
{
self.or_raise_typed(err).map_err(Exn::erased)
}
}
impl<T, E> ResultExt for std::result::Result<T, E>
where
E: std::error::Error + Send + Sync + 'static,
{
type Success = T;
type Error = E;
#[track_caller]
fn or_raise_typed<A, F>(self, err: F) -> ExnResult<Self::Success, A>
where
A: std::error::Error + Send + Sync + 'static,
F: FnOnce() -> A,
{
match self {
Ok(v) => Ok(v),
Err(e) => Err(e.and_raise_typed(err())),
}
}
#[track_caller]
fn or_error(self) -> Result<T> {
match self {
Ok(v) => Ok(v),
Err(e) => Err(e.raise()),
}
}
#[track_caller]
fn or_erased(self) -> ExnResult<Self::Success> {
match self {
Ok(v) => Ok(v),
Err(e) => Err(e.raise_erased()),
}
}
}
pub trait BoxedResultExt {
type Success;
fn or_erased(self) -> ExnResult<Self::Success>;
}
impl<T> BoxedResultExt for std::result::Result<T, Box<dyn std::error::Error + Send + Sync + 'static>> {
type Success = T;
#[track_caller]
fn or_erased(self) -> ExnResult<Self::Success> {
match self {
Ok(v) => Ok(v),
Err(e) => Err(Exn::new(crate::exn::Untyped::from_boxed(e))),
}
}
}
impl<T, E> ResultExt for ExnResult<T, E>
where
E: std::error::Error + Send + Sync + 'static,
{
type Success = T;
type Error = E;
#[track_caller]
fn or_raise_typed<A, F>(self, err: F) -> ExnResult<Self::Success, A>
where
A: std::error::Error + Send + Sync + 'static,
F: FnOnce() -> A,
{
match self {
Ok(v) => Ok(v),
Err(e) => Err(e.raise(err())),
}
}
fn or_error(self) -> Result<T> {
self.map_err(Exn::into_error)
}
#[track_caller]
fn or_erased(self) -> ExnResult<Self::Success> {
match self {
Ok(v) => Ok(v),
Err(e) => Err(e.erased()),
}
}
}