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