tin_actix_api_resp/
macros.rs

1use actix_web::http::StatusCode;
2use serde::{Deserialize, Serialize};
3
4macro_rules! status_codes {
5    (
6        $(
7            $(#[$docs:meta])*
8            ($konst:ident, $code:expr, $status:ident, $message:expr);
9        )+
10    ) => {
11        #[derive(Debug, Clone, Serialize, Deserialize)]
12        pub enum ApiRes<T: Serialize> {
13            /// Custom response with status code, error code, message, and optional data
14            Custom(u16, u32, String, Option<T>),
15            /// 200 OK with data
16            /// [[RFC7231, Section 6.3.1](https://tools.ietf.org/html/rfc7231#section-6.3.1)]
17            Ok(T),
18            /// 200 OK with additional status code and message
19            /// [[RFC7231, Section 6.3.1](https://tools.ietf.org/html/rfc7231#section-6.3.1)]
20            OkWith(u32, String, T),
21            /// 200 OK empty data
22            Empty,
23            $(
24                $(#[$docs])*
25                $konst(String),
26            )+
27        }
28
29
30        impl<T: Serialize> ApiRes<T> {
31            pub fn status(&self) -> StatusCode {
32                match self {
33                    ApiRes::Custom(status,_, _, _) => StatusCode::from_u16(*status).unwrap_or(StatusCode::INTERNAL_SERVER_ERROR),
34                    ApiRes::Ok(_) => StatusCode::OK,
35                    ApiRes::OkWith(_, _, _) => StatusCode::OK,
36                    ApiRes::Empty => StatusCode::OK,
37                    $(
38                        ApiRes::$konst(_) => StatusCode::$status,
39                    )+
40                }
41            }
42
43            pub fn code(&self) -> u32 {
44                match self {
45                    ApiRes::Custom(_,code, _, _) => *code,
46                    ApiRes::Ok(_) => 200,
47                    ApiRes::OkWith(code, _, _) => *code,
48                    ApiRes::Empty => 200,
49                    $(
50                        ApiRes::$konst(_) => $code,
51                    )+
52                }
53            }
54
55            pub fn message(&self) -> &str {
56                match self {
57                    ApiRes::Custom(_,_, msg, _) => msg,
58                    ApiRes::Ok(_) => "Success",
59                    ApiRes::OkWith(_, msg, _) => msg,
60                    ApiRes::Empty => "Success",
61                    $(
62                        ApiRes::$konst(msg) => msg,
63                    )+
64                }
65            }
66
67            pub fn data(&self) -> Option<&T> {
68                match self {
69                    ApiRes::Custom(_,_, _, data) => data.as_ref(),
70                    ApiRes::Ok(data) => Some(data),
71                    ApiRes::OkWith(_, _, data) => Some(data),
72                    ApiRes::Empty => None,
73                    _ => None,
74                }
75            }
76        }
77    };
78}
79
80status_codes! {
81    /// 100 Continue
82    /// [[RFC7231, Section 6.2.1](https://tools.ietf.org/html/rfc7231#section-6.2.1)]
83    (Continue,100, CONTINUE, "Continue");
84    /// 101 Switching Protocols
85    /// [[RFC7231, Section 6.2.2](https://tools.ietf.org/html/rfc7231#section-6.2.2)]
86    (SwitchingProtocols,101, SWITCHING_PROTOCOLS, "Switching Protocols");
87    /// 102 Processing
88    /// [[RFC2518](https://tools.ietf.org/html/rfc2518)]
89    (Processing,102, PROCESSING, "Processing");
90
91    /// 201 Created
92    /// [[RFC7231, Section 6.3.2](https://tools.ietf.org/html/rfc7231#section-6.3.2)]
93    (Created,201, CREATED, "Created");
94    /// 202 Accepted
95    /// [[RFC7231, Section 6.3.3](https://tools.ietf.org/html/rfc7231#section-6.3.3)]
96    (Accepted,202, ACCEPTED, "Accepted");
97    /// 203 Non-Authoritative Information
98    /// [[RFC7231, Section 6.3.4](https://tools.ietf.org/html/rfc7231#section-6.3.4)]
99    (NonAuthoritativeInformation,203, NON_AUTHORITATIVE_INFORMATION, "Non Authoritative Information");
100    /// 204 No Content
101    /// [[RFC7231, Section 6.3.5](https://tools.ietf.org/html/rfc7231#section-6.3.5)]
102    (NoContent,204, NO_CONTENT, "No Content");
103    /// 205 Reset Content
104    /// [[RFC7231, Section 6.3.6](https://tools.ietf.org/html/rfc7231#section-6.3.6)]
105    (ResetContent,205, RESET_CONTENT, "Reset Content");
106    /// 206 Partial Content
107    /// [[RFC7233, Section 4.1](https://tools.ietf.org/html/rfc7233#section-4.1)]
108    (PartialContent,206, PARTIAL_CONTENT, "Partial Content");
109    /// 207 Multi-Status
110    /// [[RFC4918](https://tools.ietf.org/html/rfc4918)]
111    (MultiStatus,207, MULTI_STATUS, "Multi-Status");
112    /// 208 Already Reported
113    /// [[RFC5842](https://tools.ietf.org/html/rfc5842)]
114    (AlreadyReported,208, ALREADY_REPORTED, "Already Reported");
115
116    /// 226 IM Used
117    /// [[RFC3229](https://tools.ietf.org/html/rfc3229)]
118    (IMUsed,226, IM_USED, "IM Used");
119
120    /// 300 Multiple Choices
121    /// [[RFC7231, Section 6.4.1](https://tools.ietf.org/html/rfc7231#section-6.4.1)]
122    (MultipleChoices,300, MULTIPLE_CHOICES, "Multiple Choices");
123    /// 301 Moved Permanently
124    /// [[RFC7231, Section 6.4.2](https://tools.ietf.org/html/rfc7231#section-6.4.2)]
125    (MovedPermanently,301, MOVED_PERMANENTLY, "Moved Permanently");
126    /// 302 Found
127    /// [[RFC7231, Section 6.4.3](https://tools.ietf.org/html/rfc7231#section-6.4.3)]
128    (Found,302, FOUND, "Found");
129    /// 303 See Other
130    /// [[RFC7231, Section 6.4.4](https://tools.ietf.org/html/rfc7231#section-6.4.4)]
131    (SeeOther,303, SEE_OTHER, "See Other");
132    /// 304 Not Modified
133    /// [[RFC7232, Section 4.1](https://tools.ietf.org/html/rfc7232#section-4.1)]
134    (NotModified,304, NOT_MODIFIED, "Not Modified");
135    /// 305 Use Proxy
136    /// [[RFC7231, Section 6.4.5](https://tools.ietf.org/html/rfc7231#section-6.4.5)]
137    (UseProxy,305, USE_PROXY, "Use Proxy");
138    /// 307 Temporary Redirect
139    /// [[RFC7231, Section 6.4.7](https://tools.ietf.org/html/rfc7231#section-6.4.7)]
140    (TemporaryRedirect, 307, TEMPORARY_REDIRECT, "Temporary Redirect");
141    /// 308 Permanent Redirect
142    /// [[RFC7238](https://tools.ietf.org/html/rfc7238)]
143    (PermanentRedirect,308, PERMANENT_REDIRECT, "Permanent Redirect");
144
145    /// 400 Bad Request
146    /// [[RFC7231, Section 6.5.1](https://tools.ietf.org/html/rfc7231#section-6.5.1)]
147    (BadRequest,400, BAD_REQUEST, "Bad Request");
148    /// 401 Unauthorized
149    /// [[RFC7235, Section 3.1](https://tools.ietf.org/html/rfc7235#section-3.1)]
150    (Unauthorized,401, UNAUTHORIZED, "Unauthorized");
151    /// 402 Payment Required
152    /// [[RFC7231, Section 6.5.2](https://tools.ietf.org/html/rfc7231#section-6.5.2)]
153    (PaymentRequired,402, PAYMENT_REQUIRED, "Payment Required");
154    /// 403 Forbidden
155    /// [[RFC7231, Section 6.5.3](https://tools.ietf.org/html/rfc7231#section-6.5.3)]
156    (Forbidden,403, FORBIDDEN, "Forbidden");
157    /// 404 Not Found
158    /// [[RFC7231, Section 6.5.4](https://tools.ietf.org/html/rfc7231#section-6.5.4)]
159    (NotFound,404, NOT_FOUND, "Not Found");
160    /// 405 Method Not Allowed
161    /// [[RFC7231, Section 6.5.5](https://tools.ietf.org/html/rfc7231#section-6.5.5)]
162    (MethodNotAllowed,405, METHOD_NOT_ALLOWED, "Method Not Allowed");
163    /// 406 Not Acceptable
164    /// [[RFC7231, Section 6.5.6](https://tools.ietf.org/html/rfc7231#section-6.5.6)]
165    (NotAcceptable,406, NOT_ACCEPTABLE, "Not Acceptable");
166    /// 407 Proxy Authentication Required
167    /// [[RFC7235, Section 3.2](https://tools.ietf.org/html/rfc7235#section-3.2)]
168    (ProxyAuthenticationRequired,407, PROXY_AUTHENTICATION_REQUIRED, "Proxy Authentication Required");
169    /// 408 Request Timeout
170    /// [[RFC7231, Section 6.5.7](https://tools.ietf.org/html/rfc7231#section-6.5.7)]
171    (RequestTimeout,408, REQUEST_TIMEOUT, "Request Timeout");
172    /// 409 Conflict
173    /// [[RFC7231, Section 6.5.8](https://tools.ietf.org/html/rfc7231#section-6.5.8)]
174    (Conflict,409, CONFLICT, "Conflict");
175    /// 410 Gone
176    /// [[RFC7231, Section 6.5.9](https://tools.ietf.org/html/rfc7231#section-6.5.9)]
177    (Gone,410, GONE, "Gone");
178    /// 411 Length Required
179    /// [[RFC7231, Section 6.5.10](https://tools.ietf.org/html/rfc7231#section-6.5.10)]
180    (LengthRequired,411, LENGTH_REQUIRED, "Length Required");
181    /// 412 Precondition Failed
182    /// [[RFC7232, Section 4.2](https://tools.ietf.org/html/rfc7232#section-4.2)]
183    (PreconditionFailed,412, PRECONDITION_FAILED, "Precondition Failed");
184    /// 413 Payload Too Large
185    /// [[RFC7231, Section 6.5.11](https://tools.ietf.org/html/rfc7231#section-6.5.11)]
186    (PayloadTooLarge,413, PAYLOAD_TOO_LARGE, "Payload Too Large");
187    /// 414 URI Too Long
188    /// [[RFC7231, Section 6.5.12](https://tools.ietf.org/html/rfc7231#section-6.5.12)]
189    (URITooLong,414, URI_TOO_LONG, "URI Too Long");
190    /// 415 Unsupported Media Type
191    /// [[RFC7231, Section 6.5.13](https://tools.ietf.org/html/rfc7231#section-6.5.13)]
192    (UnsupportedMediaType,415, UNSUPPORTED_MEDIA_TYPE, "Unsupported Media Type");
193    /// 416 Range Not Satisfiable
194    /// [[RFC7233, Section 4.4](https://tools.ietf.org/html/rfc7233#section-4.4)]
195    (RangeNotSatisfiable,416, RANGE_NOT_SATISFIABLE, "Range Not Satisfiable");
196    /// 417 Expectation Failed
197    /// [[RFC7231, Section 6.5.14](https://tools.ietf.org/html/rfc7231#section-6.5.14)]
198    (ExpectationFailed,417, EXPECTATION_FAILED, "Expectation Failed");
199    /// 418 I'm a teapot
200    /// [curiously not registered by IANA but [RFC2324](https://tools.ietf.org/html/rfc2324)]
201    (ImATeapot,418, IM_A_TEAPOT, "I'm a teapot");
202
203    /// 421 Misdirected Request
204    /// [RFC7540, Section 9.1.2](http://tools.ietf.org/html/rfc7540#section-9.1.2)
205    (MisdirectedRequest,421, MISDIRECTED_REQUEST, "Misdirected Request");
206    /// 422 Unprocessable Entity
207    /// [[RFC4918](https://tools.ietf.org/html/rfc4918)]
208    (UnprocessableEntity,422, UNPROCESSABLE_ENTITY, "Unprocessable Entity");
209    /// 423 Locked
210    /// [[RFC4918](https://tools.ietf.org/html/rfc4918)]
211    (Locked,423, LOCKED, "Locked");
212    /// 424 Failed Dependency
213    /// [[RFC4918](https://tools.ietf.org/html/rfc4918)]
214    (FailedDependency,424, FAILED_DEPENDENCY, "Failed Dependency");
215
216    /// 426 Upgrade Required
217    /// [[RFC7231, Section 6.5.15](https://tools.ietf.org/html/rfc7231#section-6.5.15)]
218    (UpgradeRequired,426, UPGRADE_REQUIRED, "Upgrade Required");
219
220    /// 428 Precondition Required
221    /// [[RFC6585](https://tools.ietf.org/html/rfc6585)]
222    (PreconditionRequired,428, PRECONDITION_REQUIRED, "Precondition Required");
223    /// 429 Too Many Requests
224    /// [[RFC6585](https://tools.ietf.org/html/rfc6585)]
225    (TooManyRequests,429, TOO_MANY_REQUESTS, "Too Many Requests");
226
227    /// 431 Request Header Fields Too Large
228    /// [[RFC6585](https://tools.ietf.org/html/rfc6585)]
229    (RequestHeaderFieldsTooLarge,431, REQUEST_HEADER_FIELDS_TOO_LARGE, "Request Header Fields Too Large");
230
231    /// 451 Unavailable For Legal Reasons
232    /// [[RFC7725](http://tools.ietf.org/html/rfc7725)]
233    (UnavailableForLegalReasons,451, UNAVAILABLE_FOR_LEGAL_REASONS, "Unavailable For Legal Reasons");
234
235    /// 500 Internal Server Error
236    /// [[RFC7231, Section 6.6.1](https://tools.ietf.org/html/rfc7231#section-6.6.1)]
237    (InternalServerError,500, INTERNAL_SERVER_ERROR, "Internal Server Error");
238    /// 501 Not Implemented
239    /// [[RFC7231, Section 6.6.2](https://tools.ietf.org/html/rfc7231#section-6.6.2)]
240    (NotImplemented,501, NOT_IMPLEMENTED, "Not Implemented");
241    /// 502 Bad Gateway
242    /// [[RFC7231, Section 6.6.3](https://tools.ietf.org/html/rfc7231#section-6.6.3)]
243    (BadGateway,502, BAD_GATEWAY, "Bad Gateway");
244    /// 503 Service Unavailable
245    /// [[RFC7231, Section 6.6.4](https://tools.ietf.org/html/rfc7231#section-6.6.4)]
246    (ServiceUnavailable,503, SERVICE_UNAVAILABLE, "Service Unavailable");
247    /// 504 Gateway Timeout
248    /// [[RFC7231, Section 6.6.5](https://tools.ietf.org/html/rfc7231#section-6.6.5)]
249    (GatewayTimeout,504, GATEWAY_TIMEOUT, "Gateway Timeout");
250    /// 505 HTTP Version Not Supported
251    /// [[RFC7231, Section 6.6.6](https://tools.ietf.org/html/rfc7231#section-6.6.6)]
252    (HttpVersionNotSupported,505, HTTP_VERSION_NOT_SUPPORTED, "HTTP Version Not Supported");
253    /// 506 Variant Also Negotiates
254    /// [[RFC2295](https://tools.ietf.org/html/rfc2295)]
255    (VariantAlsoNegotiates,506, VARIANT_ALSO_NEGOTIATES, "Variant Also Negotiates");
256    /// 507 Insufficient Storage
257    /// [[RFC4918](https://tools.ietf.org/html/rfc4918)]
258    (InsufficientStorage,507, INSUFFICIENT_STORAGE, "Insufficient Storage");
259    /// 508 Loop Detected
260    /// [[RFC5842](https://tools.ietf.org/html/rfc5842)]
261    (LoopDetected,508, LOOP_DETECTED, "Loop Detected");
262
263    /// 510 Not Extended
264    /// [[RFC2774](https://tools.ietf.org/html/rfc2774)]
265    (NotExtended,510, NOT_EXTENDED, "Not Extended");
266    /// 511 Network Authentication Required
267    /// [[RFC6585](https://tools.ietf.org/html/rfc6585)]
268    (NetworkAuthenticationRequired,511, NETWORK_AUTHENTICATION_REQUIRED, "Network Authentication Required");
269}