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.try_into().expect("Could not convert into a valid `StatusCode`"),
47 error: error.into(),
48 type_name: Some(std::any::type_name::<E>()),
49 }
50 }
51
52 pub fn from_str<S, M>(status: S, msg: M) -> Self
54 where
55 S: TryInto<StatusCode>,
56 S::Error: Debug,
57 M: Display + Debug + Send + Sync + 'static,
58 {
59 Self {
60 status: status.try_into().expect("Could not convert into a valid `StatusCode`"),
61 error: anyhow::Error::msg(msg),
62 type_name: None,
63 }
64 }
65 pub(crate) fn new_adhoc<M>(message: M) -> Error
67 where
68 M: Display + Debug + Send + Sync + 'static,
69 {
70 Self::from_str(StatusCode::InternalServerError, message)
71 }
72
73 pub fn status(&self) -> StatusCode {
75 self.status
76 }
77
78 pub fn set_status<S>(&mut self, status: S)
80 where
81 S: TryInto<StatusCode>,
82 S::Error: Debug,
83 {
84 self.status = status.try_into().expect("Could not convert into a valid `StatusCode`");
85 }
86
87 #[cfg(backtrace)]
105 pub fn backtrace(&self) -> Option<&std::backtrace::Backtrace> {
106 let backtrace = self.error.backtrace();
107 if let std::backtrace::BacktraceStatus::Captured = backtrace.status() {
108 Some(backtrace)
109 } else {
110 None
111 }
112 }
113
114 #[cfg(not(backtrace))]
115 #[allow(missing_docs)]
116 pub const fn backtrace(&self) -> Option<BacktracePlaceholder> {
117 None
118 }
119
120 pub fn into_inner(self) -> anyhow::Error {
123 self.error
124 }
125
126 pub fn downcast<E>(self) -> std::result::Result<E, Self>
128 where
129 E: Display + Debug + Send + Sync + 'static,
130 {
131 if self.error.downcast_ref::<E>().is_some() {
132 Ok(self.error.downcast().unwrap())
133 } else {
134 Err(self)
135 }
136 }
137
138 pub fn downcast_ref<E>(&self) -> Option<&E>
140 where
141 E: Display + Debug + Send + Sync + 'static,
142 {
143 self.error.downcast_ref::<E>()
144 }
145
146 pub fn downcast_mut<E>(&mut self) -> Option<&mut E>
148 where
149 E: Display + Debug + Send + Sync + 'static,
150 {
151 self.error.downcast_mut::<E>()
152 }
153
154 pub fn type_name(&self) -> Option<&str> {
156 self.type_name
157 }
158
159 pub fn from_display<D: Display>(error: D) -> Self {
167 anyhow::Error::msg(error.to_string()).into()
168 }
169
170 pub fn from_debug<D: Debug>(error: D) -> Self {
178 anyhow::Error::msg(format!("{:?}", error)).into()
179 }
180}
181
182impl Display for Error {
183 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
184 Display::fmt(&self.error, formatter)
185 }
186}
187
188impl Debug for Error {
189 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
190 Debug::fmt(&self.error, formatter)
191 }
192}
193
194impl<E: Into<anyhow::Error>> From<E> for Error {
195 fn from(error: E) -> Self {
196 Self::new(StatusCode::InternalServerError, error)
197 }
198}
199
200impl AsRef<dyn StdError + Send + Sync> for Error {
201 fn as_ref(&self) -> &(dyn StdError + Send + Sync + 'static) {
202 self.error.as_ref()
203 }
204}
205
206impl AsRef<StatusCode> for Error {
207 fn as_ref(&self) -> &StatusCode {
208 &self.status
209 }
210}
211
212impl AsMut<StatusCode> for Error {
213 fn as_mut(&mut self) -> &mut StatusCode {
214 &mut self.status
215 }
216}
217
218impl AsRef<dyn StdError> for Error {
219 fn as_ref(&self) -> &(dyn StdError + 'static) {
220 self.error.as_ref()
221 }
222}
223
224impl From<Error> for Box<dyn StdError + Send + Sync + 'static> {
225 fn from(error: Error) -> Self {
226 error.error.into()
227 }
228}
229
230impl From<Error> for Box<dyn StdError + 'static> {
231 fn from(error: Error) -> Self {
232 Box::<dyn StdError + Send + Sync>::from(error.error)
233 }
234}
235
236impl AsRef<anyhow::Error> for Error {
237 fn as_ref(&self) -> &anyhow::Error {
238 &self.error
239 }
240}