1use std::{error::Error, fmt};
12
13use axum::{
14 http::StatusCode,
15 response::{IntoResponse, Response},
16 Json,
17};
18use serde::Serialize;
19use serde_json;
20
21#[derive(Debug)]
23pub enum ErrResp {
24 ErrAuth(Option<String>),
25 ErrDb(Option<String>),
26 ErrIntMsg(Option<String>),
27 ErrNotFound(Option<String>),
28 ErrParam(Option<String>),
29 ErrPerm(Option<String>),
30 ErrRsc(Option<String>),
31 ErrUnknown(Option<String>),
32 Custom(u16, &'static str, Option<String>),
33}
34
35#[derive(Serialize)]
37struct RespJson<'a> {
38 code: &'a str,
39 #[serde(skip_serializing_if = "Option::is_none")]
40 message: Option<&'a str>,
41}
42
43pub const E_AUTH: &'static str = "err_auth";
45pub const E_DB: &'static str = "err_db";
47pub const E_INT_MSG: &'static str = "err_int_msg";
49pub const E_NOT_FOUND: &'static str = "err_not_found";
51pub const E_PARAM: &'static str = "err_param";
53pub const E_PERM: &'static str = "err_perm";
55pub const E_RSC: &'static str = "err_rsc";
57pub const E_UNKNOWN: &'static str = "err_unknown";
59
60pub fn to_json(code: &str, message: Option<&str>) -> String {
62 serde_json::to_string(&RespJson { code, message }).unwrap()
63}
64
65impl ErrResp {
66 fn resp_json(&self) -> RespJson {
67 match *self {
68 ErrResp::ErrAuth(ref desc) => RespJson {
69 code: E_AUTH,
70 message: match desc.as_ref() {
71 None => None,
72 Some(desc) => Some(desc.as_str()),
73 },
74 },
75 ErrResp::ErrDb(ref desc) => RespJson {
76 code: E_DB,
77 message: match desc.as_ref() {
78 None => None,
79 Some(desc) => Some(desc.as_str()),
80 },
81 },
82 ErrResp::ErrIntMsg(ref desc) => RespJson {
83 code: E_INT_MSG,
84 message: match desc.as_ref() {
85 None => None,
86 Some(desc) => Some(desc.as_str()),
87 },
88 },
89 ErrResp::ErrNotFound(ref desc) => RespJson {
90 code: E_NOT_FOUND,
91 message: match desc.as_ref() {
92 None => None,
93 Some(desc) => Some(desc.as_str()),
94 },
95 },
96 ErrResp::ErrParam(ref desc) => RespJson {
97 code: E_PARAM,
98 message: match desc.as_ref() {
99 None => None,
100 Some(desc) => Some(desc.as_str()),
101 },
102 },
103 ErrResp::ErrPerm(ref desc) => RespJson {
104 code: E_PERM,
105 message: match desc.as_ref() {
106 None => None,
107 Some(desc) => Some(desc.as_str()),
108 },
109 },
110 ErrResp::ErrRsc(ref desc) => RespJson {
111 code: E_RSC,
112 message: match desc.as_ref() {
113 None => None,
114 Some(desc) => Some(desc.as_str()),
115 },
116 },
117 ErrResp::ErrUnknown(ref desc) => RespJson {
118 code: E_UNKNOWN,
119 message: match desc.as_ref() {
120 None => None,
121 Some(desc) => Some(desc.as_str()),
122 },
123 },
124 ErrResp::Custom(_, err_code, ref desc) => RespJson {
125 code: err_code,
126 message: desc.as_deref(),
127 },
128 }
129 }
130}
131
132impl fmt::Display for ErrResp {
133 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
134 write!(f, "{}", serde_json::to_string(&self.resp_json()).unwrap())
135 }
136}
137
138impl Error for ErrResp {}
139
140impl IntoResponse for ErrResp {
141 fn into_response(self) -> Response {
142 match self {
143 ErrResp::ErrAuth(_) => (StatusCode::UNAUTHORIZED, Json(self.resp_json())),
144 ErrResp::ErrDb(_) => (StatusCode::SERVICE_UNAVAILABLE, Json(self.resp_json())),
145 ErrResp::ErrIntMsg(_) => (StatusCode::SERVICE_UNAVAILABLE, Json(self.resp_json())),
146 ErrResp::ErrNotFound(_) => (StatusCode::NOT_FOUND, Json(self.resp_json())),
147 ErrResp::ErrParam(_) => (StatusCode::BAD_REQUEST, Json(self.resp_json())),
148 ErrResp::ErrPerm(_) => (StatusCode::FORBIDDEN, Json(self.resp_json())),
149 ErrResp::ErrRsc(_) => (StatusCode::SERVICE_UNAVAILABLE, Json(self.resp_json())),
150 ErrResp::ErrUnknown(_) => (StatusCode::INTERNAL_SERVER_ERROR, Json(self.resp_json())),
151 ErrResp::Custom(code, _, _) => {
152 (StatusCode::from_u16(code).unwrap(), Json(self.resp_json()))
153 }
154 }
155 .into_response()
156 }
157}