http_error/
option_ext.rs

1use std::{error, fmt};
2
3use http::StatusCode;
4
5use crate::HttpError;
6
7#[derive(Debug)]
8pub struct StatusError {
9    status: StatusCode,
10    context: &'static str,
11}
12
13macro_rules! trait_fn {
14    ($name:ident) => {
15        fn $name(self, context: &'static str) -> Result<T, StatusError>;
16    };
17}
18macro_rules! impl_fn {
19    ($name:ident, $status:ident) => {
20        fn $name(self, context: &'static str) -> Result<T, StatusError> {
21            self.ok_or_else(|| StatusError {
22                status: StatusCode::$status,
23                context,
24            })
25        }
26    };
27}
28
29pub trait OptionExt<T> {
30    // 400 Bad Request
31    trait_fn!(ok_or_bad_request);
32    // 401 Unauthorized
33    trait_fn!(ok_or_unauthorized);
34    // 402 Payment Required
35    trait_fn!(ok_or_payment_required);
36    // 403 Forbidden
37    trait_fn!(ok_or_forbidden);
38    // 404 Not Found
39    trait_fn!(ok_or_not_found);
40    // 405 Method Not Allowed
41    trait_fn!(ok_or_method_not_allowed);
42    // 406 Not Acceptable
43    trait_fn!(ok_or_not_acceptable);
44    // 407 Proxy Authentication Required
45    trait_fn!(ok_or_proxy_authentication_required);
46    // 408 Request Timeout
47    trait_fn!(ok_or_request_timeout);
48    // 409 Conflict
49    trait_fn!(ok_or_conflict);
50    // 410 Gone
51    trait_fn!(ok_or_gone);
52    // 411 Length Required
53    trait_fn!(ok_or_length_required);
54    // 412 Precondition Failed
55    trait_fn!(ok_or_precondition_failed);
56    // 413 Payload Too Large
57    trait_fn!(ok_or_payload_too_large);
58    // 414 URI Too Long
59    trait_fn!(ok_or_uri_too_long);
60    // 415 Unsupported Media Type
61    trait_fn!(ok_or_unsupported_media_type);
62    // 416 Range Not Satisfiable
63    trait_fn!(ok_or_range_not_satisfiable);
64    // 417 Expectation Failed
65    trait_fn!(ok_or_expectation_failed);
66    // 418 I'm a teapot
67    trait_fn!(ok_or_im_a_teapot);
68
69    // 421 Misdirected Request
70    trait_fn!(ok_or_misdirected_request);
71    // 422 Unprocessable Entity
72    trait_fn!(ok_or_unprocessable_entity);
73    // 423 Locked
74    trait_fn!(ok_or_locked);
75    // 424 Failed Dependency
76    trait_fn!(ok_or_failed_dependency);
77
78    // 426 Upgrade Required
79    trait_fn!(ok_or_upgrade_required);
80
81    // 428 Precondition Required
82    trait_fn!(ok_or_precondition_required);
83    // 429 Too Many Requests
84    trait_fn!(ok_or_too_many_requests);
85
86    // 431 Request Header Fields Too Large
87    trait_fn!(ok_or_request_header_fields_too_large);
88
89    // 451 Unavailable For Legal Reasons
90    trait_fn!(ok_or_unavailable_for_legal_reasons);
91
92    // 500 Internal Server Error
93    trait_fn!(ok_or_internal_server_error);
94    // 501 Not Implemented
95    trait_fn!(ok_or_not_implemented);
96    // 502 Bad Gateway
97    trait_fn!(ok_or_bad_gateway);
98    // 503 Service Unavailable
99    trait_fn!(ok_or_service_unavailable);
100    // 504 Gateway Timeout
101    trait_fn!(ok_or_gateway_timeout);
102    // 505 HTTP Version Not Supported
103    trait_fn!(ok_or_http_version_not_supported);
104    // 506 Variant Also Negotiates
105    trait_fn!(ok_or_variant_also_negotiates);
106    // 507 Insufficient Storage
107    trait_fn!(ok_or_insufficient_storage);
108    // 508 Loop Detected
109    trait_fn!(ok_or_loop_detected);
110
111    // 510 Not Extended
112    trait_fn!(ok_or_not_extended);
113    // 511 Network Authentication Required
114    trait_fn!(ok_or_network_authentication_required);
115}
116impl<T> OptionExt<T> for Option<T> {
117    impl_fn!(ok_or_bad_request, BAD_REQUEST);
118    impl_fn!(ok_or_unauthorized, UNAUTHORIZED);
119    impl_fn!(ok_or_payment_required, PAYMENT_REQUIRED);
120    impl_fn!(ok_or_forbidden, FORBIDDEN);
121    impl_fn!(ok_or_not_found, NOT_FOUND);
122    impl_fn!(ok_or_method_not_allowed, METHOD_NOT_ALLOWED);
123    impl_fn!(ok_or_not_acceptable, NOT_ACCEPTABLE);
124    impl_fn!(
125        ok_or_proxy_authentication_required,
126        PROXY_AUTHENTICATION_REQUIRED
127    );
128    impl_fn!(ok_or_request_timeout, REQUEST_TIMEOUT);
129    impl_fn!(ok_or_conflict, CONFLICT);
130    impl_fn!(ok_or_gone, GONE);
131    impl_fn!(ok_or_length_required, LENGTH_REQUIRED);
132    impl_fn!(ok_or_precondition_failed, PRECONDITION_FAILED);
133    impl_fn!(ok_or_payload_too_large, PAYLOAD_TOO_LARGE);
134    impl_fn!(ok_or_uri_too_long, URI_TOO_LONG);
135    impl_fn!(ok_or_unsupported_media_type, UNSUPPORTED_MEDIA_TYPE);
136    impl_fn!(ok_or_range_not_satisfiable, RANGE_NOT_SATISFIABLE);
137    impl_fn!(ok_or_expectation_failed, EXPECTATION_FAILED);
138    impl_fn!(ok_or_im_a_teapot, IM_A_TEAPOT);
139
140    impl_fn!(ok_or_misdirected_request, MISDIRECTED_REQUEST);
141    impl_fn!(ok_or_unprocessable_entity, UNPROCESSABLE_ENTITY);
142    impl_fn!(ok_or_locked, LOCKED);
143    impl_fn!(ok_or_failed_dependency, FAILED_DEPENDENCY);
144
145    impl_fn!(ok_or_upgrade_required, UPGRADE_REQUIRED);
146
147    impl_fn!(ok_or_precondition_required, PRECONDITION_REQUIRED);
148    impl_fn!(ok_or_too_many_requests, TOO_MANY_REQUESTS);
149
150    impl_fn!(
151        ok_or_request_header_fields_too_large,
152        REQUEST_HEADER_FIELDS_TOO_LARGE
153    );
154
155    impl_fn!(
156        ok_or_unavailable_for_legal_reasons,
157        UNAVAILABLE_FOR_LEGAL_REASONS
158    );
159
160    impl_fn!(ok_or_internal_server_error, INTERNAL_SERVER_ERROR);
161    impl_fn!(ok_or_not_implemented, NOT_IMPLEMENTED);
162    impl_fn!(ok_or_bad_gateway, BAD_GATEWAY);
163    impl_fn!(ok_or_service_unavailable, SERVICE_UNAVAILABLE);
164    impl_fn!(ok_or_gateway_timeout, GATEWAY_TIMEOUT);
165    impl_fn!(ok_or_http_version_not_supported, HTTP_VERSION_NOT_SUPPORTED);
166    impl_fn!(ok_or_variant_also_negotiates, VARIANT_ALSO_NEGOTIATES);
167    impl_fn!(ok_or_insufficient_storage, INSUFFICIENT_STORAGE);
168    impl_fn!(ok_or_loop_detected, LOOP_DETECTED);
169
170    impl_fn!(ok_or_not_extended, NOT_EXTENDED);
171    impl_fn!(
172        ok_or_network_authentication_required,
173        NETWORK_AUTHENTICATION_REQUIRED
174    );
175}
176
177impl error::Error for StatusError {
178    fn source(&self) -> Option<&(dyn error::Error + 'static)> {
179        None
180    }
181}
182
183impl fmt::Display for StatusError {
184    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
185        f.write_str(self.context)
186    }
187}
188
189impl HttpError for StatusError {
190    fn status_code(&self) -> StatusCode {
191        self.status
192    }
193}