use std::error::Error as StdError;
use crate::{IntoResponse, Response, StatusCode, ThisError};
pub type BoxError = Box<dyn StdError + Send + Sync>;
#[derive(ThisError, Debug)]
pub enum Error {
#[error("response")]
Responder(Response),
#[error(transparent)]
Boxed(BoxError),
#[error("report")]
Report(BoxError, Response),
}
impl Error {
pub fn boxed<T>(t: T) -> Self
where
T: Into<BoxError>,
{
Self::Boxed(t.into())
}
#[inline]
pub fn is<T>(&self) -> bool
where
T: StdError + 'static,
{
match self {
Self::Boxed(e) | Self::Report(e, _) => e.is::<T>(),
Self::Responder(_) => false,
}
}
#[inline]
pub fn downcast<T>(self) -> Result<T, Self>
where
T: StdError + 'static,
{
if let Self::Boxed(e) = self {
return match e.downcast::<T>() {
Ok(e) => Ok(*e),
Err(e) => Err(Self::Boxed(e)),
};
}
if let Self::Report(e, r) = self {
return match e.downcast::<T>() {
Ok(e) => Ok(*e),
Err(e) => Err(Self::Report(e, r)),
};
}
Err(self)
}
#[inline]
pub fn downcast_ref<T>(&self) -> Option<&T>
where
T: StdError + 'static,
{
if let Self::Boxed(e) = self {
return e.downcast_ref::<T>();
}
if let Self::Report(e, _) = self {
return e.downcast_ref::<T>();
}
None
}
#[inline]
pub fn downcast_mut<T>(&mut self) -> Option<&mut T>
where
T: StdError + 'static,
{
if let Self::Boxed(e) = self {
return e.downcast_mut::<T>();
}
if let Self::Report(e, _) = self {
return e.downcast_mut::<T>();
}
None
}
}
impl<E, T> From<(E, T)> for Error
where
E: Into<BoxError>,
T: IntoResponse,
{
fn from((e, t): (E, T)) -> Self {
Self::Report(e.into(), t.into_response())
}
}
impl From<http::Error> for Error {
fn from(e: http::Error) -> Self {
(e, StatusCode::BAD_REQUEST).into()
}
}
impl From<hyper::Error> for Error {
fn from(e: hyper::Error) -> Self {
(e, StatusCode::BAD_REQUEST).into()
}
}
impl From<std::convert::Infallible> for Error {
fn from(e: std::convert::Infallible) -> Self {
Self::boxed(e)
}
}
impl From<std::io::Error> for Error {
fn from(e: std::io::Error) -> Self {
Self::boxed(e)
}
}
impl From<BoxError> for Error {
fn from(value: BoxError) -> Self {
Self::Boxed(value)
}
}