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 trait_fn!(ok_or_bad_request);
32 trait_fn!(ok_or_unauthorized);
34 trait_fn!(ok_or_payment_required);
36 trait_fn!(ok_or_forbidden);
38 trait_fn!(ok_or_not_found);
40 trait_fn!(ok_or_method_not_allowed);
42 trait_fn!(ok_or_not_acceptable);
44 trait_fn!(ok_or_proxy_authentication_required);
46 trait_fn!(ok_or_request_timeout);
48 trait_fn!(ok_or_conflict);
50 trait_fn!(ok_or_gone);
52 trait_fn!(ok_or_length_required);
54 trait_fn!(ok_or_precondition_failed);
56 trait_fn!(ok_or_payload_too_large);
58 trait_fn!(ok_or_uri_too_long);
60 trait_fn!(ok_or_unsupported_media_type);
62 trait_fn!(ok_or_range_not_satisfiable);
64 trait_fn!(ok_or_expectation_failed);
66 trait_fn!(ok_or_im_a_teapot);
68
69 trait_fn!(ok_or_misdirected_request);
71 trait_fn!(ok_or_unprocessable_entity);
73 trait_fn!(ok_or_locked);
75 trait_fn!(ok_or_failed_dependency);
77
78 trait_fn!(ok_or_upgrade_required);
80
81 trait_fn!(ok_or_precondition_required);
83 trait_fn!(ok_or_too_many_requests);
85
86 trait_fn!(ok_or_request_header_fields_too_large);
88
89 trait_fn!(ok_or_unavailable_for_legal_reasons);
91
92 trait_fn!(ok_or_internal_server_error);
94 trait_fn!(ok_or_not_implemented);
96 trait_fn!(ok_or_bad_gateway);
98 trait_fn!(ok_or_service_unavailable);
100 trait_fn!(ok_or_gateway_timeout);
102 trait_fn!(ok_or_http_version_not_supported);
104 trait_fn!(ok_or_variant_also_negotiates);
106 trait_fn!(ok_or_insufficient_storage);
108 trait_fn!(ok_or_loop_detected);
110
111 trait_fn!(ok_or_not_extended);
113 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}