1use crate::response::Response;
2use thiserror::Error as ThisError;
3
4#[derive(Debug, ThisError)]
6pub enum Error {
7 #[error("not found")]
8 NotFound,
9
10 #[error("unauthorized")]
11 Unauthorized,
12
13 #[error("bad request: {0}")]
14 BadRequest(String),
15
16 #[error("payload too large")]
17 PayloadTooLarge,
18
19 #[error("method not allowed")]
20 MethodNotAllowed,
21
22 #[error("internal error: {0}")]
23 Internal(String),
24
25 #[error("json error: {0}")]
26 Json(#[from] serde_json::Error),
27
28 #[error("io error: {0}")]
29 Io(#[from] std::io::Error),
30
31 #[error("response")]
33 Response(Box<Response>),
34}
35
36pub type Result<T> = std::result::Result<T, Error>;
37
38impl Error {
39 pub fn custom(status: u16, body: impl IntoResponse) -> Self {
41 Error::Response(Box::new(body.into_response().status(status)))
42 }
43
44 pub fn into_response(self) -> Response {
45 match self {
46 Error::NotFound => Response::text("Not Found").status(404),
47 Error::Unauthorized => Response::text("Unauthorized").status(401),
48 Error::BadRequest(msg) => Response::text(msg).status(400),
49 Error::PayloadTooLarge => Response::text("Payload Too Large").status(413),
50 Error::MethodNotAllowed => Response::text("Method Not Allowed").status(405),
51 Error::Internal(msg) => Response::text(msg).status(500),
52 Error::Json(err) => Response::text(format!("JSON error: {err}")).status(400),
53 Error::Io(err) => Response::text(format!("IO error: {err}")).status(500),
54 Error::Response(res) => *res,
55 }
56 }
57}
58
59pub trait IntoResponse {
61 fn into_response(self) -> Response;
62}
63
64impl IntoResponse for Response {
65 fn into_response(self) -> Response {
66 self
67 }
68}
69
70impl IntoResponse for Error {
71 fn into_response(self) -> Response {
72 Error::into_response(self)
73 }
74}
75
76impl IntoResponse for String {
77 fn into_response(self) -> Response {
78 Response::text(self)
79 }
80}
81
82impl IntoResponse for &str {
83 fn into_response(self) -> Response {
84 Response::text(self)
85 }
86}