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}