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