1use std::error::Error as StdError;
4use std::fmt::{self, Debug, Display};
5
6use crate::StatusCode;
7use std::convert::TryInto;
8
9pub type Result<T> = std::result::Result<T, Error>;
14
15pub struct Error {
17 error: anyhow::Error,
18 status: crate::StatusCode,
19 type_name: Option<&'static str>,
20}
21
22#[allow(unreachable_pub)]
23#[derive(Debug)]
24#[doc(hidden)]
25pub struct BacktracePlaceholder;
26
27impl Display for BacktracePlaceholder {
28 fn fmt(&self, _: &mut fmt::Formatter<'_>) -> fmt::Result {
29 unreachable!()
30 }
31}
32
33impl Error {
34 pub fn new<S, E>(status: S, error: E) -> Self
40 where
41 S: TryInto<StatusCode>,
42 S::Error: Debug,
43 E: Into<anyhow::Error>,
44 {
45 Self {
46 status: status
47 .try_into()
48 .expect("Could not convert into a valid `StatusCode`"),
49 error: error.into(),
50 type_name: Some(std::any::type_name::<E>()),
51 }
52 }
53
54 pub fn from_str<S, M>(status: S, msg: M) -> Self
56 where
57 S: TryInto<StatusCode>,
58 S::Error: Debug,
59 M: Display + Debug + Send + Sync + 'static,
60 {
61 Self {
62 status: status
63 .try_into()
64 .expect("Could not convert into a valid `StatusCode`"),
65 error: anyhow::Error::msg(msg),
66 type_name: None,
67 }
68 }
69 pub(crate) fn new_adhoc<M>(message: M) -> Error
71 where
72 M: Display + Debug + Send + Sync + 'static,
73 {
74 Self::from_str(StatusCode::InternalServerError, message)
75 }
76
77 pub fn status(&self) -> StatusCode {
79 self.status
80 }
81
82 pub fn set_status<S>(&mut self, status: S)
84 where
85 S: TryInto<StatusCode>,
86 S::Error: Debug,
87 {
88 self.status = status
89 .try_into()
90 .expect("Could not convert into a valid `StatusCode`");
91 }
92
93 #[cfg(backtrace)]
111 pub fn backtrace(&self) -> Option<&std::backtrace::Backtrace> {
112 let backtrace = self.error.backtrace();
113 if let std::backtrace::BacktraceStatus::Captured = backtrace.status() {
114 Some(backtrace)
115 } else {
116 None
117 }
118 }
119
120 #[cfg(not(backtrace))]
121 #[allow(missing_docs)]
122 pub const fn backtrace(&self) -> Option<BacktracePlaceholder> {
123 None
124 }
125
126 pub fn into_inner(self) -> anyhow::Error {
129 self.error
130 }
131
132 pub fn downcast<E>(self) -> std::result::Result<E, Self>
134 where
135 E: Display + Debug + Send + Sync + 'static,
136 {
137 if self.error.downcast_ref::<E>().is_some() {
138 Ok(self.error.downcast().unwrap())
139 } else {
140 Err(self)
141 }
142 }
143
144 pub fn downcast_ref<E>(&self) -> Option<&E>
146 where
147 E: Display + Debug + Send + Sync + 'static,
148 {
149 self.error.downcast_ref::<E>()
150 }
151
152 pub fn downcast_mut<E>(&mut self) -> Option<&mut E>
154 where
155 E: Display + Debug + Send + Sync + 'static,
156 {
157 self.error.downcast_mut::<E>()
158 }
159
160 pub fn type_name(&self) -> Option<&str> {
162 self.type_name.as_deref()
163 }
164
165 pub fn from_display<D: Display>(error: D) -> Self {
173 anyhow::Error::msg(error.to_string()).into()
174 }
175
176 pub fn from_debug<D: Debug>(error: D) -> Self {
184 anyhow::Error::msg(format!("{:?}", error)).into()
185 }
186}
187
188impl Display for Error {
189 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
190 Display::fmt(&self.error, formatter)
191 }
192}
193
194impl Debug for Error {
195 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
196 Debug::fmt(&self.error, formatter)
197 }
198}
199
200impl<E: Into<anyhow::Error>> From<E> for Error {
201 fn from(error: E) -> Self {
202 Self::new(StatusCode::InternalServerError, error)
203 }
204}
205
206impl AsRef<dyn StdError + Send + Sync> for Error {
207 fn as_ref(&self) -> &(dyn StdError + Send + Sync + 'static) {
208 self.error.as_ref()
209 }
210}
211
212impl AsRef<StatusCode> for Error {
213 fn as_ref(&self) -> &StatusCode {
214 &self.status
215 }
216}
217
218impl AsMut<StatusCode> for Error {
219 fn as_mut(&mut self) -> &mut StatusCode {
220 &mut self.status
221 }
222}
223
224impl AsRef<dyn StdError> for Error {
225 fn as_ref(&self) -> &(dyn StdError + 'static) {
226 self.error.as_ref()
227 }
228}
229
230impl From<Error> for Box<dyn StdError + Send + Sync + 'static> {
231 fn from(error: Error) -> Self {
232 error.error.into()
233 }
234}
235
236impl From<Error> for Box<dyn StdError + 'static> {
237 fn from(error: Error) -> Self {
238 Box::<dyn StdError + Send + Sync>::from(error.error)
239 }
240}
241
242impl AsRef<anyhow::Error> for Error {
243 fn as_ref(&self) -> &anyhow::Error {
244 &self.error
245 }
246}