http_types/status_code.rs
1use serde::de::{Error as DeError, Unexpected, Visitor};
2use serde::{Deserialize, Deserializer, Serialize, Serializer};
3use std::fmt::{self, Display};
4
5/// HTTP response status codes.
6///
7/// As defined by [rfc7231 section 6](https://tools.ietf.org/html/rfc7231#section-6).
8/// [Read more](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status)
9#[repr(u16)]
10#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
11pub enum StatusCode {
12 /// 100 Continue
13 ///
14 /// This interim response indicates that everything so far is OK and that
15 /// the client should continue the request, or ignore the response if
16 /// the request is already finished.
17 Continue = 100,
18
19 /// 101 Switching Protocols
20 ///
21 /// This code is sent in response to an Upgrade request header from the
22 /// client, and indicates the protocol the server is switching to.
23 SwitchingProtocols = 101,
24
25 /// 103 Early Hints
26 ///
27 /// This status code is primarily intended to be used with the Link header,
28 /// letting the user agent start preloading resources while the server
29 /// prepares a response.
30 EarlyHints = 103,
31
32 /// 200 Ok
33 ///
34 /// The request has succeeded
35 Ok = 200,
36
37 /// 201 Created
38 ///
39 /// The request has succeeded and a new resource has been created as a
40 /// result. This is typically the response sent after POST requests, or
41 /// some PUT requests.
42 Created = 201,
43
44 /// 202 Accepted
45 ///
46 /// The request has been received but not yet acted upon. It is
47 /// noncommittal, since there is no way in HTTP to later send an
48 /// asynchronous response indicating the outcome of the request. It is
49 /// intended for cases where another process or server handles the request,
50 /// or for batch processing.
51 Accepted = 202,
52
53 /// 203 Non Authoritative Information
54 ///
55 /// This response code means the returned meta-information is not exactly
56 /// the same as is available from the origin server, but is collected
57 /// from a local or a third-party copy. This is mostly used for mirrors
58 /// or backups of another resource. Except for that specific case, the
59 /// "200 OK" response is preferred to this status.
60 NonAuthoritativeInformation = 203,
61
62 /// 204 No Content
63 ///
64 /// There is no content to send for this request, but the headers may be
65 /// useful. The user-agent may update its cached headers for this
66 /// resource with the new ones.
67 NoContent = 204,
68
69 /// 205 Reset Content
70 ///
71 /// Tells the user-agent to reset the document which sent this request.
72 ResetContent = 205,
73
74 /// 206 Partial Content
75 ///
76 /// This response code is used when the Range header is sent from the client
77 /// to request only part of a resource.
78 PartialContent = 206,
79
80 /// 207 Multi-Status
81 ///
82 /// A Multi-Status response conveys information about
83 /// multiple resources in situations where multiple
84 /// status codes might be appropriate.
85 MultiStatus = 207,
86
87 /// 226 Im Used
88 ///
89 /// The server has fulfilled a GET request for the resource, and the
90 /// response is a representation of the result of one or more
91 /// instance-manipulations applied to the current instance.
92 ImUsed = 226,
93
94 /// 300 Multiple Choice
95 ///
96 /// The request has more than one possible response. The user-agent or user
97 /// should choose one of them. (There is no standardized way of choosing
98 /// one of the responses, but HTML links to the possibilities are
99 /// recommended so the user can pick.)
100 MultipleChoice = 300,
101
102 /// 301 Moved Permanently
103 ///
104 /// The URL of the requested resource has been changed permanently. The new
105 /// URL is given in the response.
106 MovedPermanently = 301,
107
108 /// 302 Found
109 ///
110 /// This response code means that the URI of requested resource has been
111 /// changed temporarily. Further changes in the URI might be made in the
112 /// future. Therefore, this same URI should be used by the client in
113 /// future requests.
114 Found = 302,
115
116 /// 303 See Other
117 ///
118 /// The server sent this response to direct the client to get the requested
119 /// resource at another URI with a GET request.
120 SeeOther = 303,
121
122 /// 304 Not Modified
123 ///
124 /// This is used for caching purposes. It tells the client that the response
125 /// has not been modified, so the client can continue to use the same
126 /// cached version of the response.
127 NotModified = 304,
128
129 /// 307 Temporary Redirect
130 ///
131 /// The server sends this response to direct the client to get the requested
132 /// resource at another URI with same method that was used in the prior
133 /// request. This has the same semantics as the 302 Found HTTP response
134 /// code, with the exception that the user agent must not change the
135 /// HTTP method used: If a POST was used in the first request, a POST must
136 /// be used in the second request.
137 TemporaryRedirect = 307,
138
139 /// 308 Permanent Redirect
140 ///
141 /// This means that the resource is now permanently located at another URI,
142 /// specified by the Location: HTTP Response header. This has the same
143 /// semantics as the 301 Moved Permanently HTTP response code, with the
144 /// exception that the user agent must not change the HTTP method
145 /// used: If a POST was used in the first request, a POST must be used in
146 /// the second request.
147 PermanentRedirect = 308,
148
149 /// 400 Bad Request
150 ///
151 /// The server could not understand the request due to invalid syntax.
152 BadRequest = 400,
153
154 /// 401 Unauthorized
155 ///
156 /// Although the HTTP standard specifies "unauthorized", semantically this
157 /// response means "unauthenticated". That is, the client must
158 /// authenticate itself to get the requested response.
159 Unauthorized = 401,
160
161 /// 402 Payment Required
162 ///
163 /// This response code is reserved for future use. The initial aim for
164 /// creating this code was using it for digital payment systems, however
165 /// this status code is used very rarely and no standard convention
166 /// exists.
167 PaymentRequired = 402,
168
169 /// 403 Forbidden
170 ///
171 /// The client does not have access rights to the content; that is, it is
172 /// unauthorized, so the server is refusing to give the requested
173 /// resource. Unlike 401, the client's identity is known to the server.
174 Forbidden = 403,
175
176 /// 404 Not Found
177 ///
178 /// The server can not find requested resource. In the browser, this means
179 /// the URL is not recognized. In an API, this can also mean that the
180 /// endpoint is valid but the resource itself does not exist. Servers
181 /// may also send this response instead of 403 to hide the existence of
182 /// a resource from an unauthorized client. This response code is probably
183 /// the most famous one due to its frequent occurrence on the web.
184 NotFound = 404,
185
186 /// 405 Method Not Allowed
187 ///
188 /// The request method is known by the server but has been disabled and
189 /// cannot be used. For example, an API may forbid DELETE-ing a
190 /// resource. The two mandatory methods, GET and HEAD, must never be
191 /// disabled and should not return this error code.
192 MethodNotAllowed = 405,
193
194 /// 406 Not Acceptable
195 ///
196 /// This response is sent when the web server, after performing
197 /// server-driven content negotiation, doesn't find any content that
198 /// conforms to the criteria given by the user agent.
199 NotAcceptable = 406,
200
201 /// 407 Proxy Authentication Required
202 ///
203 /// This is similar to 401 but authentication is needed to be done by a
204 /// proxy.
205 ProxyAuthenticationRequired = 407,
206
207 /// 408 Request Timeout
208 ///
209 /// This response is sent on an idle connection by some servers, even
210 /// without any previous request by the client. It means that the server
211 /// would like to shut down this unused connection. This response is
212 /// used much more since some browsers, like Chrome, Firefox 27+,
213 /// or IE9, use HTTP pre-connection mechanisms to speed up surfing. Also
214 /// note that some servers merely shut down the connection without
215 /// sending this message.
216 RequestTimeout = 408,
217
218 /// 409 Conflict
219 ///
220 /// This response is sent when a request conflicts with the current state of
221 /// the server.
222 Conflict = 409,
223
224 /// 410 Gone
225 ///
226 /// This response is sent when the requested content has been permanently
227 /// deleted from server, with no forwarding address. Clients are
228 /// expected to remove their caches and links to the resource. The HTTP
229 /// specification intends this status code to be used for "limited-time,
230 /// promotional services". APIs should not feel compelled to indicate
231 /// resources that have been deleted with this status code.
232 Gone = 410,
233
234 /// 411 Length Required
235 ///
236 /// Server rejected the request because the Content-Length header field is
237 /// not defined and the server requires it.
238 LengthRequired = 411,
239
240 /// 412 Precondition Failed
241 ///
242 /// The client has indicated preconditions in its headers which the server
243 /// does not meet.
244 PreconditionFailed = 412,
245
246 /// 413 Payload Too Large
247 ///
248 /// Request entity is larger than limits defined by server; the server might
249 /// close the connection or return an Retry-After header field.
250 PayloadTooLarge = 413,
251
252 /// 414 URI Too Long
253 ///
254 /// The URI requested by the client is longer than the server is willing to
255 /// interpret.
256 UriTooLong = 414,
257
258 /// 415 Unsupported Media Type
259 ///
260 /// The media format of the requested data is not supported by the server,
261 /// so the server is rejecting the request.
262 UnsupportedMediaType = 415,
263
264 /// 416 Requested Range Not Satisfiable
265 ///
266 /// The range specified by the Range header field in the request can't be
267 /// fulfilled; it's possible that the range is outside the size of the
268 /// target URI's data.
269 RequestedRangeNotSatisfiable = 416,
270
271 /// 417 Expectation Failed
272 ///
273 /// This response code means the expectation indicated by the Expect request
274 /// header field can't be met by the server.
275 ExpectationFailed = 417,
276 ///
277 /// 418 I'm a teapot
278 ///
279 /// The server refuses the attempt to brew coffee with a teapot.
280 ImATeapot = 418,
281
282 /// 421 Misdirected Request
283 ///
284 /// The request was directed at a server that is not able to produce a
285 /// response. This can be sent by a server that is not configured to
286 /// produce responses for the combination of scheme and authority that
287 /// are included in the request URI.
288 MisdirectedRequest = 421,
289
290 /// 422 Unprocessable Entity
291 ///
292 /// The request was well-formed but was unable to be followed due to
293 /// semantic errors.
294 UnprocessableEntity = 422,
295
296 /// 423 Locked
297 ///
298 /// The resource that is being accessed is locked.
299 Locked = 423,
300
301 /// 424 Failed Dependency
302 ///
303 /// The request failed because it depended on another request and that
304 /// request failed (e.g., a PROPPATCH).
305 FailedDependency = 424,
306
307 /// 425 Too Early
308 ///
309 /// Indicates that the server is unwilling to risk processing a request that
310 /// might be replayed.
311 TooEarly = 425,
312
313 /// 426 Upgrade Required
314 ///
315 /// The server refuses to perform the request using the current protocol but
316 /// might be willing to do so after the client upgrades to a different
317 /// protocol. The server sends an Upgrade header in a 426 response to
318 /// indicate the required protocol(s).
319 UpgradeRequired = 426,
320
321 /// 428 Precondition Required
322 ///
323 /// The origin server requires the request to be conditional. This response
324 /// is intended to prevent the 'lost update' problem, where a client
325 /// GETs a resource's state, modifies it, and PUTs it back to the
326 /// server, when meanwhile a third party has modified the state on the
327 /// server, leading to a conflict.
328 PreconditionRequired = 428,
329
330 /// 429 Too Many Requests
331 ///
332 /// The user has sent too many requests in a given amount of time ("rate
333 /// limiting").
334 TooManyRequests = 429,
335
336 /// 431 Request Header Fields Too Large
337 ///
338 /// The server is unwilling to process the request because its header fields
339 /// are too large. The request may be resubmitted after reducing the
340 /// size of the request header fields.
341 RequestHeaderFieldsTooLarge = 431,
342
343 /// 451 Unavailable For Legal Reasons
344 ///
345 /// The user-agent requested a resource that cannot legally be provided,
346 /// such as a web page censored by a government.
347 UnavailableForLegalReasons = 451,
348
349 /// 500 Internal Server Error
350 ///
351 /// The server has encountered a situation it doesn't know how to handle.
352 InternalServerError = 500,
353
354 /// 501 Not Implemented
355 ///
356 /// The request method is not supported by the server and cannot be handled.
357 /// The only methods that servers are required to support (and therefore
358 /// that must not return this code) are GET and HEAD.
359 NotImplemented = 501,
360
361 /// 502 Bad Gateway
362 ///
363 /// This error response means that the server, while working as a gateway to
364 /// get a response needed to handle the request, got an invalid
365 /// response.
366 BadGateway = 502,
367
368 /// 503 Service Unavailable
369 ///
370 /// The server is not ready to handle the request. Common causes are a
371 /// server that is down for maintenance or that is overloaded. Note that
372 /// together with this response, a user-friendly page explaining the
373 /// problem should be sent. This responses should be used for temporary
374 /// conditions and the Retry-After: HTTP header should, if possible, contain
375 /// the estimated time before the recovery of the service. The webmaster
376 /// must also take care about the caching-related headers that are sent
377 /// along with this response, as these temporary condition responses
378 /// should usually not be cached.
379 ServiceUnavailable = 503,
380
381 /// 504 Gateway Timeout
382 ///
383 /// This error response is given when the server is acting as a gateway and
384 /// cannot get a response in time.
385 GatewayTimeout = 504,
386
387 /// 505 HTTP Version Not Supported
388 ///
389 /// The HTTP version used in the request is not supported by the server.
390 HttpVersionNotSupported = 505,
391
392 /// 506 Variant Also Negotiates
393 ///
394 /// The server has an internal configuration error: the chosen variant
395 /// resource is configured to engage in transparent content negotiation
396 /// itself, and is therefore not a proper end point in the negotiation
397 /// process.
398 VariantAlsoNegotiates = 506,
399
400 /// 507 Insufficient Storage
401 ///
402 /// The server is unable to store the representation needed to complete the
403 /// request.
404 InsufficientStorage = 507,
405
406 /// 508 Loop Detected
407 ///
408 /// The server detected an infinite loop while processing the request.
409 LoopDetected = 508,
410
411 /// 510 Not Extended
412 ///
413 /// Further extensions to the request are required for the server to fulfil
414 /// it.
415 NotExtended = 510,
416
417 /// 511 Network Authentication Required
418 ///
419 /// The 511 status code indicates that the client needs to authenticate to
420 /// gain network access.
421 NetworkAuthenticationRequired = 511,
422}
423
424impl StatusCode {
425 /// Returns `true` if the status code is `1xx` range.
426 ///
427 /// If this returns `true` it indicates that the request was received,
428 /// continuing process.
429 pub fn is_informational(&self) -> bool {
430 let num: u16 = (*self).into();
431 (100..200).contains(&num)
432 }
433
434 /// Returns `true` if the status code is the `2xx` range.
435 ///
436 /// If this returns `true` it indicates that the request was successfully
437 /// received, understood, and accepted.
438 pub fn is_success(&self) -> bool {
439 let num: u16 = (*self).into();
440 (200..300).contains(&num)
441 }
442
443 /// Returns `true` if the status code is the `3xx` range.
444 ///
445 /// If this returns `true` it indicates that further action needs to be
446 /// taken in order to complete the request.
447 pub fn is_redirection(&self) -> bool {
448 let num: u16 = (*self).into();
449 (300..400).contains(&num)
450 }
451
452 /// Returns `true` if the status code is the `4xx` range.
453 ///
454 /// If this returns `true` it indicates that the request contains bad syntax
455 /// or cannot be fulfilled.
456 pub fn is_client_error(&self) -> bool {
457 let num: u16 = (*self).into();
458 (400..500).contains(&num)
459 }
460
461 /// Returns `true` if the status code is the `5xx` range.
462 ///
463 /// If this returns `true` it indicates that the server failed to fulfill an
464 /// apparently valid request.
465 pub fn is_server_error(&self) -> bool {
466 let num: u16 = (*self).into();
467 (500..600).contains(&num)
468 }
469
470 /// The canonical reason for a given status code
471 pub fn canonical_reason(&self) -> &'static str {
472 match self {
473 StatusCode::Continue => "Continue",
474 StatusCode::SwitchingProtocols => "Switching Protocols",
475 StatusCode::EarlyHints => "Early Hints",
476 StatusCode::Ok => "OK",
477 StatusCode::Created => "Created",
478 StatusCode::Accepted => "Accepted",
479 StatusCode::NonAuthoritativeInformation => "Non Authoritative Information",
480 StatusCode::NoContent => "No Content",
481 StatusCode::ResetContent => "Reset Content",
482 StatusCode::PartialContent => "Partial Content",
483 StatusCode::MultiStatus => "Multi-Status",
484 StatusCode::ImUsed => "Im Used",
485 StatusCode::MultipleChoice => "Multiple Choice",
486 StatusCode::MovedPermanently => "Moved Permanently",
487 StatusCode::Found => "Found",
488 StatusCode::SeeOther => "See Other",
489 StatusCode::NotModified => "Modified",
490 StatusCode::TemporaryRedirect => "Temporary Redirect",
491 StatusCode::PermanentRedirect => "Permanent Redirect",
492 StatusCode::BadRequest => "Bad Request",
493 StatusCode::Unauthorized => "Unauthorized",
494 StatusCode::PaymentRequired => "Payment Required",
495 StatusCode::Forbidden => "Forbidden",
496 StatusCode::NotFound => "Not Found",
497 StatusCode::MethodNotAllowed => "Method Not Allowed",
498 StatusCode::NotAcceptable => "Not Acceptable",
499 StatusCode::ProxyAuthenticationRequired => "Proxy Authentication Required",
500 StatusCode::RequestTimeout => "Request Timeout",
501 StatusCode::Conflict => "Conflict",
502 StatusCode::Gone => "Gone",
503 StatusCode::LengthRequired => "Length Required",
504 StatusCode::PreconditionFailed => "Precondition Failed",
505 StatusCode::PayloadTooLarge => "Payload Too Large",
506 StatusCode::UriTooLong => "URI Too Long",
507 StatusCode::UnsupportedMediaType => "Unsupported Media Type",
508 StatusCode::RequestedRangeNotSatisfiable => "Requested Range Not Satisfiable",
509 StatusCode::ExpectationFailed => "Expectation Failed",
510 StatusCode::ImATeapot => "I'm a teapot",
511 StatusCode::MisdirectedRequest => "Misdirected Request",
512 StatusCode::UnprocessableEntity => "Unprocessable Entity",
513 StatusCode::Locked => "Locked",
514 StatusCode::FailedDependency => "Failed Dependency",
515 StatusCode::TooEarly => "Too Early",
516 StatusCode::UpgradeRequired => "Upgrade Required",
517 StatusCode::PreconditionRequired => "Precondition Required",
518 StatusCode::TooManyRequests => "Too Many Requests",
519 StatusCode::RequestHeaderFieldsTooLarge => "Request Header Fields Too Large",
520 StatusCode::UnavailableForLegalReasons => "Unavailable For Legal Reasons",
521 StatusCode::InternalServerError => "Internal Server Error",
522 StatusCode::NotImplemented => "Not Implemented",
523 StatusCode::BadGateway => "Bad Gateway",
524 StatusCode::ServiceUnavailable => "Service Unavailable",
525 StatusCode::GatewayTimeout => "Gateway Timeout",
526 StatusCode::HttpVersionNotSupported => "HTTP Version Not Supported",
527 StatusCode::VariantAlsoNegotiates => "Variant Also Negotiates",
528 StatusCode::InsufficientStorage => "Insufficient Storage",
529 StatusCode::LoopDetected => "Loop Detected",
530 StatusCode::NotExtended => "Not Extended",
531 StatusCode::NetworkAuthenticationRequired => "Network Authentication Required",
532 }
533 }
534}
535
536impl Serialize for StatusCode {
537 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
538 where
539 S: Serializer,
540 {
541 let value: u16 = *self as u16;
542 serializer.serialize_u16(value)
543 }
544}
545
546struct StatusCodeU16Visitor;
547
548impl<'de> Visitor<'de> for StatusCodeU16Visitor {
549 type Value = StatusCode;
550
551 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
552 write!(formatter, "a u16 representing the status code")
553 }
554
555 fn visit_i16<E>(self, v: i16) -> Result<Self::Value, E>
556 where
557 E: DeError,
558 {
559 self.visit_u16(v as u16)
560 }
561
562 fn visit_i32<E>(self, v: i32) -> Result<Self::Value, E>
563 where
564 E: DeError,
565 {
566 self.visit_u16(v as u16)
567 }
568
569 fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E>
570 where
571 E: DeError,
572 {
573 self.visit_u16(v as u16)
574 }
575
576 fn visit_u16<E>(self, v: u16) -> Result<Self::Value, E>
577 where
578 E: DeError,
579 {
580 use std::convert::TryFrom;
581 match StatusCode::try_from(v) {
582 Ok(status_code) => Ok(status_code),
583 Err(_) => Err(DeError::invalid_value(
584 Unexpected::Unsigned(v as u64),
585 &self,
586 )),
587 }
588 }
589
590 fn visit_u32<E>(self, v: u32) -> Result<Self::Value, E>
591 where
592 E: DeError,
593 {
594 self.visit_u16(v as u16)
595 }
596
597 fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
598 where
599 E: DeError,
600 {
601 self.visit_u16(v as u16)
602 }
603}
604
605impl<'de> Deserialize<'de> for StatusCode {
606 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
607 where
608 D: Deserializer<'de>,
609 {
610 deserializer.deserialize_any(StatusCodeU16Visitor)
611 }
612}
613
614impl From<StatusCode> for u16 {
615 fn from(code: StatusCode) -> u16 {
616 code as u16
617 }
618}
619
620impl std::convert::TryFrom<u16> for StatusCode {
621 type Error = crate::Error;
622
623 fn try_from(num: u16) -> Result<Self, Self::Error> {
624 match num {
625 100 => Ok(StatusCode::Continue),
626 101 => Ok(StatusCode::SwitchingProtocols),
627 103 => Ok(StatusCode::EarlyHints),
628 200 => Ok(StatusCode::Ok),
629 201 => Ok(StatusCode::Created),
630 202 => Ok(StatusCode::Accepted),
631 203 => Ok(StatusCode::NonAuthoritativeInformation),
632 204 => Ok(StatusCode::NoContent),
633 205 => Ok(StatusCode::ResetContent),
634 206 => Ok(StatusCode::PartialContent),
635 207 => Ok(StatusCode::MultiStatus),
636 226 => Ok(StatusCode::ImUsed),
637 300 => Ok(StatusCode::MultipleChoice),
638 301 => Ok(StatusCode::MovedPermanently),
639 302 => Ok(StatusCode::Found),
640 303 => Ok(StatusCode::SeeOther),
641 304 => Ok(StatusCode::NotModified),
642 307 => Ok(StatusCode::TemporaryRedirect),
643 308 => Ok(StatusCode::PermanentRedirect),
644 400 => Ok(StatusCode::BadRequest),
645 401 => Ok(StatusCode::Unauthorized),
646 402 => Ok(StatusCode::PaymentRequired),
647 403 => Ok(StatusCode::Forbidden),
648 404 => Ok(StatusCode::NotFound),
649 405 => Ok(StatusCode::MethodNotAllowed),
650 406 => Ok(StatusCode::NotAcceptable),
651 407 => Ok(StatusCode::ProxyAuthenticationRequired),
652 408 => Ok(StatusCode::RequestTimeout),
653 409 => Ok(StatusCode::Conflict),
654 410 => Ok(StatusCode::Gone),
655 411 => Ok(StatusCode::LengthRequired),
656 412 => Ok(StatusCode::PreconditionFailed),
657 413 => Ok(StatusCode::PayloadTooLarge),
658 414 => Ok(StatusCode::UriTooLong),
659 415 => Ok(StatusCode::UnsupportedMediaType),
660 416 => Ok(StatusCode::RequestedRangeNotSatisfiable),
661 417 => Ok(StatusCode::ExpectationFailed),
662 418 => Ok(StatusCode::ImATeapot),
663 421 => Ok(StatusCode::MisdirectedRequest),
664 422 => Ok(StatusCode::UnprocessableEntity),
665 423 => Ok(StatusCode::Locked),
666 424 => Ok(StatusCode::FailedDependency),
667 425 => Ok(StatusCode::TooEarly),
668 426 => Ok(StatusCode::UpgradeRequired),
669 428 => Ok(StatusCode::PreconditionRequired),
670 429 => Ok(StatusCode::TooManyRequests),
671 431 => Ok(StatusCode::RequestHeaderFieldsTooLarge),
672 451 => Ok(StatusCode::UnavailableForLegalReasons),
673 500 => Ok(StatusCode::InternalServerError),
674 501 => Ok(StatusCode::NotImplemented),
675 502 => Ok(StatusCode::BadGateway),
676 503 => Ok(StatusCode::ServiceUnavailable),
677 504 => Ok(StatusCode::GatewayTimeout),
678 505 => Ok(StatusCode::HttpVersionNotSupported),
679 506 => Ok(StatusCode::VariantAlsoNegotiates),
680 507 => Ok(StatusCode::InsufficientStorage),
681 508 => Ok(StatusCode::LoopDetected),
682 510 => Ok(StatusCode::NotExtended),
683 511 => Ok(StatusCode::NetworkAuthenticationRequired),
684 _ => crate::bail!("Invalid status code"),
685 }
686 }
687}
688
689impl PartialEq<StatusCode> for u16 {
690 fn eq(&self, other: &StatusCode) -> bool {
691 *self == *other as u16
692 }
693}
694
695impl PartialEq<u16> for StatusCode {
696 fn eq(&self, other: &u16) -> bool {
697 *self as u16 == *other
698 }
699}
700
701impl Display for StatusCode {
702 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
703 write!(f, "{}", *self as u16)
704 }
705}
706
707#[cfg(test)]
708mod test {
709 use super::StatusCode;
710 #[test]
711 fn serde_as_u16() -> Result<(), serde_json::Error> {
712 let status_code: StatusCode = serde_json::from_str("202")?;
713 assert_eq!(StatusCode::Accepted, status_code);
714 assert_eq!(
715 Some(202),
716 serde_json::to_value(&StatusCode::Accepted)?.as_u64()
717 );
718 Ok(())
719 }
720}