1use std::fmt;
2
3use axum::{
4 http::StatusCode,
5 response::{IntoResponse, Response},
6 Json,
7};
8use serde::Serialize;
9
10fn as_u16<S>(status: &StatusCode, serializer: S) -> Result<S::Ok, S::Error>
11where
12 S: serde::Serializer,
13{
14 serializer.serialize_u16(status.as_u16())
15}
16
17#[derive(Debug, Default, Serialize)]
18pub struct Nothing;
19
20#[derive(Debug, Default, Serialize)]
21pub struct JsonListMeta {
22 #[serde(skip_serializing_if = "Option::is_none")]
23 total: Option<usize>,
24 #[serde(skip_serializing_if = "Option::is_none")]
25 next: Option<String>,
26 #[serde(skip_serializing_if = "Option::is_none")]
27 prev: Option<String>,
28}
29
30impl JsonListMeta {
31 pub fn next(mut self, next: String) -> Self {
32 self.next = Some(next);
33 self
34 }
35
36 pub fn prev(mut self, prev: String) -> Self {
37 self.prev = Some(prev);
38 self
39 }
40
41 pub fn total(mut self, total: usize) -> Self {
42 self.total = Some(total);
43 self
44 }
45}
46
47#[derive(Debug, Serialize)]
48pub struct JsonResponse<T = Nothing, M = Nothing> {
49 #[serde(serialize_with = "as_u16")]
50 pub status: StatusCode,
51 pub content: T,
52 pub meta: M,
53}
54
55impl<T, M> Default for JsonResponse<T, M>
56where
57 T: Default,
58 M: Default,
59{
60 fn default() -> Self {
61 Self {
62 status: StatusCode::OK,
63 content: T::default(),
64 meta: M::default(),
65 }
66 }
67}
68
69impl JsonResponse {
70 pub fn new() -> Self {
71 Self::default()
72 }
73}
74
75impl<T> JsonResponse<T> {
76 pub fn with_content(content: T) -> Self {
77 Self {
78 status: StatusCode::OK,
79 content,
80 meta: Nothing,
81 }
82 }
83}
84
85impl<T, M> JsonResponse<T, M> {
86 pub fn content<T2>(self, content: T2) -> JsonResponse<T2, M> {
87 JsonResponse {
88 status: self.status,
89 content,
90 meta: self.meta,
91 }
92 }
93
94 pub fn meta<M2>(self, meta: M2) -> JsonResponse<T, M2> {
95 JsonResponse {
96 status: self.status,
97 content: self.content,
98 meta,
99 }
100 }
101}
102
103impl<T, M> fmt::Display for JsonResponse<T, M>
104where
105 T: Serialize,
106 M: Serialize,
107{
108 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
109 f.write_str("JsonResponse: ")?;
110 f.write_str(&serde_json::to_string_pretty(self).map_err(|_err| fmt::Error)?)
111 }
112}
113
114impl<T, M> IntoResponse for JsonResponse<T, M>
115where
116 T: Serialize,
117 M: Serialize,
118{
119 fn into_response(self) -> Response {
120 (self.status, Json(&self)).into_response()
121 }
122}
123
124#[derive(Default, Debug, Serialize)]
127pub struct JsonError<T = Nothing> {
128 #[serde(serialize_with = "as_u16")]
129 pub status: StatusCode,
130 pub code: &'static str,
131 #[serde(skip_serializing_if = "Option::is_none")]
132 pub hint: Option<String>,
133 pub content: T,
134}
135
136impl JsonError {
137 pub fn new(status: StatusCode, code: &'static str) -> Self {
138 Self {
139 status,
140 code,
141 ..Default::default()
142 }
143 }
144}
145
146impl<T> JsonError<T> {
147 pub fn with_content(status: StatusCode, code: &'static str, content: T) -> Self {
148 Self {
149 status,
150 code,
151 hint: None,
152 content,
153 }
154 }
155
156 pub fn hint(mut self, hint: String) -> Self {
157 self.hint = Some(hint);
158 self
159 }
160
161 pub fn content<B>(self, content: B) -> JsonError<B> {
162 JsonError {
163 status: self.status,
164 code: self.code,
165 hint: self.hint,
166 content,
167 }
168 }
169}
170
171impl<T> fmt::Display for JsonError<T> {
172 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
173 f.write_str("JsonError: ")?;
174 f.write_str(self.code)
175 }
176}
177
178impl<T> IntoResponse for JsonError<T>
179where
180 T: Serialize + 'static,
181{
182 fn into_response(self) -> axum::response::Response {
183 (self.status, Json(&self)).into_response()
184 }
185}