http_types_rs/
status_code.rs

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