Skip to main content

axum_error_sets/
code.rs

1use super::*;
2use axum_core::response::IntoResponse;
3
4macro_rules! define_codes {
5    (
6        $(
7            $(#[$meta:meta])*
8            code $name:ident => $status:expr;
9        )*
10    ) => {
11        $(
12            $(#[$meta])*
13            #[derive(Debug, Clone, Copy, Default)]
14            pub struct $name<T = ()>(pub T);
15
16            impl<T, R, S> From<$name<R>> for ErrorSet<S, T>
17            where
18                R: Into<S>,
19                T: Contains<$name>,
20            {
21                fn from(err: $name<R>) -> Self {
22                    ErrorSet::new(err)
23                }
24            }
25
26            impl<T> From<T> for $name<T> {
27                fn from(inner: T) -> Self {
28                    Self(inner)
29                }
30            }
31
32
33            impl<T> std::ops::Deref for $name<T> {
34                type Target = T;
35
36                fn deref(&self) -> &Self::Target {
37                    &self.0
38                }
39            }
40
41            impl<T> std::ops::DerefMut for $name<T> {
42                fn deref_mut(&mut self) -> &mut Self::Target {
43                    &mut self.0
44                }
45            }
46
47            impl<T> StatusWrapper for $name<T> {
48                const STATUS_CODE: StatusCode = $status;
49
50                type Inner = T;
51                type Pure = $name;
52
53                fn into_inner(self) -> Self::Inner {
54                    self.0
55                }
56            }
57
58            impl<T: serde::Serialize> IntoResponse for $name<T> {
59                fn into_response(self) -> Response {
60                    (Self::STATUS_CODE, axum::extract::Json(self.0)).into_response()
61                }
62            }
63
64            #[cfg(feature = "aide")]
65            impl<T: schemars::JsonSchema> aide::OperationOutput for $name<T> {
66                type Inner = T;
67
68                // fn operation_response(
69                //     _ctx: &mut aide::generate::GenContext,
70                //     _operation: &mut aide::openapi::Operation,
71                // ) -> Option<aide::openapi::Response> {
72                //     None
73                // }
74
75                fn inferred_responses(
76                    _ctx: &mut aide::generate::GenContext,
77                    _operation: &mut aide::openapi::Operation,
78                ) -> Vec<(Option<u16>, aide::openapi::Response)> {
79                    use aide::openapi::SchemaObject;
80
81                    vec![(
82                        Some(Self::STATUS_CODE.as_u16()),
83                        aide::openapi::Response {
84                            description: Default::default(),
85                            content: std::iter::once((
86                                "application/json".to_string(),
87                                aide::openapi::MediaType {
88                                    schema: Some(SchemaObject {
89                                        json_schema: schemars::schema_for!(T),
90                                        example: None,
91                                        external_docs: None,
92                                    }),
93                                    ..Default::default()
94                                },
95                            ))
96                            .collect(),
97                            ..Default::default()
98                        },
99                    )]
100                }
101            }
102        )*
103    };
104}
105
106define_codes!(
107    /// 400 Bad Request
108    code BadRequest => StatusCode::BAD_REQUEST;
109
110    /// 401 Unauthorized
111    code Unauthorized => StatusCode::UNAUTHORIZED;
112
113    /// 402 Payment Required
114    code PaymentRequired => StatusCode::PAYMENT_REQUIRED;
115
116    /// 403 Forbidden
117    code Forbidden => StatusCode::FORBIDDEN;
118
119    /// 404 Not Found
120    code NotFound => StatusCode::NOT_FOUND;
121
122    /// 405 Method Not Allowed
123    code MethodNotAllowed => StatusCode::METHOD_NOT_ALLOWED;
124
125    /// 406 Not Acceptable
126    code NotAcceptable => StatusCode::NOT_ACCEPTABLE;
127
128    /// 407 Proxy Authentication Required
129    code ProxyAuthenticationRequired => StatusCode::PROXY_AUTHENTICATION_REQUIRED;
130
131    /// 408 Request Timeout
132    code RequestTimeout => StatusCode::REQUEST_TIMEOUT;
133
134    /// 409 Conflict
135    code Conflict => StatusCode::CONFLICT;
136
137    /// 410 Gone
138    code Gone => StatusCode::GONE;
139
140    /// 411 Length Required
141    code LengthRequired => StatusCode::LENGTH_REQUIRED;
142
143    /// 412 Precondition Failed
144    code PreconditionFailed => StatusCode::PRECONDITION_FAILED;
145
146    // /// 413 Content Too Large
147    // code ContentTooLarge => StatusCode::CONTENT_TOO_LARGE;
148
149    /// 414 URI Too Long
150    code UriTooLong => StatusCode::URI_TOO_LONG;
151
152    /// 415 Unsupported Media Type
153    code UnsupportedMediaType => StatusCode::UNSUPPORTED_MEDIA_TYPE;
154
155    /// 416 Range Not Satisfiable
156    code RangeNotSatisfiable => StatusCode::RANGE_NOT_SATISFIABLE;
157
158    /// 417 Expectation Failed
159    code ExpectationFailed => StatusCode::EXPECTATION_FAILED;
160
161    /// 418 I'm a teapot
162    code ImATeapot => StatusCode::IM_A_TEAPOT;
163
164    /// 421 Misdirected Request
165    code MisdirectedRequest => StatusCode::MISDIRECTED_REQUEST;
166
167    /// 422 Unprocessable Entity
168    code UnprocessableEntity => StatusCode::UNPROCESSABLE_ENTITY;
169
170    /// 423 Locked
171    code Locked => StatusCode::LOCKED;
172
173    /// 424 Failed Dependency
174    code FailedDependency => StatusCode::FAILED_DEPENDENCY;
175
176    // /// 425 Too Early
177    // code TooEarly => StatusCode::TOO_EARLY;
178
179    /// 426 Upgrade Required
180    code UpgradeRequired => StatusCode::UPGRADE_REQUIRED;
181
182    /// 428 Precondition Required
183    code PreconditionRequired => StatusCode::PRECONDITION_REQUIRED;
184
185    /// 429 Too Many Requests
186    code TooManyRequests => StatusCode::TOO_MANY_REQUESTS;
187
188    /// 431 Request Header Fields Too Large
189    code RequestHeaderFieldsTooLarge => StatusCode::REQUEST_HEADER_FIELDS_TOO_LARGE;
190
191    /// 451 Unavailable For Legal Reasons
192    code UnavailableForLegalReasons => StatusCode::UNAVAILABLE_FOR_LEGAL_REASONS;
193
194    /// 500 Internal Server Error
195    code InternalServerError => StatusCode::INTERNAL_SERVER_ERROR;
196
197    /// 501 Not Implemented
198    code NotImplemented => StatusCode::NOT_IMPLEMENTED;
199
200    /// 502 Bad Gateway
201    code BadGateway => StatusCode::BAD_GATEWAY;
202
203    /// 503 Service Unavailable
204    code ServiceUnavailable => StatusCode::SERVICE_UNAVAILABLE;
205
206    /// 504 Gateway Timeout
207    code GatewayTimeout => StatusCode::GATEWAY_TIMEOUT;
208
209    /// 505 HTTP Version Not Supported
210    code HttpVersionNotSupported => StatusCode::HTTP_VERSION_NOT_SUPPORTED;
211
212    /// 506 Variant Also Negotiates
213    code VariantAlsoNegotiates => StatusCode::VARIANT_ALSO_NEGOTIATES;
214
215    /// 507 Insufficient Storage
216    code InsufficientStorage => StatusCode::INSUFFICIENT_STORAGE;
217
218    /// 508 Loop Detected
219    code LoopDetected => StatusCode::LOOP_DETECTED;
220
221    /// 510 Not Extended
222    code NotExtended => StatusCode::NOT_EXTENDED;
223
224    /// 511 Network Authentication Required
225    code NetworkAuthenticationRequired => StatusCode::NETWORK_AUTHENTICATION_REQUIRED;
226);