1use std::fmt;
4
5use axum::{
6 http::StatusCode,
7 response::{IntoResponse, Response},
8};
9
10#[derive(Debug)]
12pub enum Error {
13 BadRequest(String),
15 Forbidden,
17 NotFound,
19 Server(String),
21 Render(String),
23}
24
25impl Error {
26 pub fn status(&self) -> StatusCode {
28 match self {
29 Self::BadRequest(_) => StatusCode::BAD_REQUEST,
30 Self::Forbidden => StatusCode::FORBIDDEN,
31 Self::NotFound => StatusCode::NOT_FOUND,
32 Self::Server(_) | Self::Render(_) => StatusCode::INTERNAL_SERVER_ERROR,
33 }
34 }
35}
36
37impl fmt::Display for Error {
38 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
39 match self {
40 Self::BadRequest(msg) => write!(f, "{msg}"),
41 Self::Forbidden => write!(f, "Forbidden"),
42 Self::NotFound => write!(f, "Not Found"),
43 Self::Server(msg) | Self::Render(msg) => write!(f, "{msg}"),
44 }
45 }
46}
47
48impl std::error::Error for Error {}
49
50impl From<askama::Error> for Error {
51 fn from(value: askama::Error) -> Self {
52 Self::Render(value.to_string())
53 }
54}
55
56impl From<rango_store::StoreError> for Error {
57 fn from(value: rango_store::StoreError) -> Self {
58 Self::Server(value.to_string())
59 }
60}
61
62impl IntoResponse for Error {
63 fn into_response(self) -> Response {
64 if self.status().is_server_error() {
65 tracing::error!(error = %self);
66 }
67 (self.status(), self.to_string()).into_response()
68 }
69}
70
71#[cfg(test)]
72mod tests {
73 use super::*;
74
75 #[test]
76 fn statuses() {
77 assert_eq!(
78 Error::BadRequest("x".into()).status(),
79 StatusCode::BAD_REQUEST
80 );
81 assert_eq!(Error::Forbidden.status(), StatusCode::FORBIDDEN);
82 assert_eq!(Error::NotFound.status(), StatusCode::NOT_FOUND);
83 assert!(Error::Server("x".into()).status().is_server_error());
84 assert!(Error::Render("x".into()).status().is_server_error());
85 }
86
87 #[test]
88 fn display() {
89 assert_eq!(Error::BadRequest("msg".into()).to_string(), "msg");
90 assert_eq!(Error::Forbidden.to_string(), "Forbidden");
91 assert_eq!(Error::NotFound.to_string(), "Not Found");
92 assert_eq!(Error::Server("msg".into()).to_string(), "msg");
93 }
94}