1use std::error::Error as StdError;
2
3use crate::{IntoResponse, Response, StatusCode, ThisError};
4
5pub type BoxError = Box<dyn StdError + Send + Sync>;
7
8#[derive(Debug, ThisError)]
10pub enum Error {
11 #[error(transparent)]
13 Boxed(BoxError),
14 #[error("response")]
16 Responder(Box<Response>),
17 #[error("report")]
19 Report(BoxError, Box<Response>),
20}
21
22impl Error {
23 pub fn boxed<T>(t: T) -> Self
25 where
26 T: Into<BoxError>,
27 {
28 Self::Boxed(t.into())
29 }
30
31 #[must_use]
33 #[inline]
34 pub fn is<T>(&self) -> bool
35 where
36 T: StdError + 'static,
37 {
38 match self {
39 Self::Boxed(e) | Self::Report(e, _) => e.is::<T>(),
40 Self::Responder(_) => false,
41 }
42 }
43
44 #[inline]
50 pub fn downcast<T>(self) -> Result<T, Self>
51 where
52 T: StdError + 'static,
53 {
54 if let Self::Boxed(e) = self {
55 return match e.downcast::<T>() {
56 Ok(e) => Ok(*e),
57 Err(e) => Err(Self::Boxed(e)),
58 };
59 }
60 if let Self::Report(e, r) = self {
61 return match e.downcast::<T>() {
62 Ok(e) => Ok(*e),
63 Err(e) => Err(Self::Report(e, r)),
64 };
65 }
66 Err(self)
67 }
68
69 #[must_use]
71 #[inline]
72 pub fn downcast_ref<T>(&self) -> Option<&T>
73 where
74 T: StdError + 'static,
75 {
76 if let Self::Boxed(e) = self {
77 return e.downcast_ref::<T>();
78 }
79 if let Self::Report(e, _) = self {
80 return e.downcast_ref::<T>();
81 }
82 None
83 }
84
85 #[inline]
87 pub fn downcast_mut<T>(&mut self) -> Option<&mut T>
88 where
89 T: StdError + 'static,
90 {
91 if let Self::Boxed(e) = self {
92 return e.downcast_mut::<T>();
93 }
94 if let Self::Report(e, _) = self {
95 return e.downcast_mut::<T>();
96 }
97 None
98 }
99}
100
101impl<E, T> From<(E, T)> for Error
102where
103 E: Into<BoxError>,
104 T: IntoResponse,
105{
106 fn from((e, t): (E, T)) -> Self {
107 Self::Report(e.into(), Box::new(t.into_response()))
108 }
109}
110
111impl From<http::Error> for Error {
112 fn from(e: http::Error) -> Self {
113 (e, StatusCode::BAD_REQUEST).into()
114 }
115}
116
117impl From<hyper::Error> for Error {
118 fn from(e: hyper::Error) -> Self {
119 (e, StatusCode::BAD_REQUEST).into()
120 }
121}
122
123impl From<std::convert::Infallible> for Error {
124 fn from(e: std::convert::Infallible) -> Self {
125 Self::boxed(e)
126 }
127}
128
129impl From<std::io::Error> for Error {
130 fn from(e: std::io::Error) -> Self {
131 Self::boxed(e)
132 }
133}
134
135impl From<BoxError> for Error {
136 fn from(value: BoxError) -> Self {
137 Self::Boxed(value)
138 }
139}