1pub use anyhow::{Error, Result};
2
3use crate::http::{Body, StatusCode};
4use crate::response::Response;
5
6pub trait CatchExt {
7 type Value;
8 type Error;
9 fn catch<E>(self) -> Result<Result<Self::Value, E>, Self::Error>
10 where
11 E: std::error::Error + Send + Sync + 'static;
12}
13
14impl<T> CatchExt for Result<T> {
15 type Value = T;
16 type Error = Error;
17
18 fn catch<E>(self) -> Result<Result<Self::Value, E>, Self::Error>
19 where
20 E: std::error::Error + Send + Sync + 'static,
21 {
22 match self {
23 Ok(value) => Ok(Ok(value)),
24 Err(err) => match err.downcast::<E>() {
25 Ok(e) => Ok(Err(e)),
26 Err(err) => Err(err),
27 },
28 }
29 }
30}
31
32#[derive(Debug, thiserror::Error)]
33#[error("StatusError: {}", .status.as_str())]
34pub struct StatusError {
35 pub status: StatusCode,
36}
37
38impl StatusError {
39 pub const NOT_FOUND: Self = Self {
40 status: StatusCode::NOT_FOUND,
41 };
42
43 pub fn new(status: StatusCode) -> Self {
44 Self { status }
45 }
46}
47
48impl From<StatusError> for Response {
49 fn from(e: StatusError) -> Self {
50 let body = match e.status.canonical_reason() {
51 Some(s) => s.into(),
52 None => Body::empty(),
53 };
54 Response::new(e.status, body)
55 }
56}