1 //! HTTP status codes
2 //!
3 //! This module contains HTTP-status code related structs an errors. The main
4 //! type in this module is `StatusCode` which is not intended to be used through
5 //! this module but rather the `http::StatusCode` type.
6 //!
7 //! # Examples
8 //!
9 //! ```
10 //! use http::StatusCode;
11 //!
12 //! assert_eq!(StatusCode::from_u16(200).unwrap(), StatusCode::OK);
13 //! assert_eq!(StatusCode::NOT_FOUND, 404);
14 //! assert!(StatusCode::OK.is_success());
15 //! ```
16 
17 use std::convert::TryFrom;
18 use std::num::NonZeroU16;
19 use std::error::Error;
20 use std::fmt;
21 use std::str::FromStr;
22 
23 /// An HTTP status code (`status-code` in RFC 7230 et al.).
24 ///
25 /// Constants are provided for known status codes, including those in the IANA
26 /// [HTTP Status Code Registry](
27 /// https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml).
28 ///
29 /// Status code values in the range 100-999 (inclusive) are supported by this
30 /// type. Values in the range 100-599 are semantically classified by the most
31 /// significant digit. See [`StatusCode::is_success`], etc. Values above 599
32 /// are unclassified but allowed for legacy compatibility, though their use is
33 /// discouraged. Applications may interpret such values as protocol errors.
34 ///
35 /// # Examples
36 ///
37 /// ```
38 /// use http::StatusCode;
39 ///
40 /// assert_eq!(StatusCode::from_u16(200).unwrap(), StatusCode::OK);
41 /// assert_eq!(StatusCode::NOT_FOUND.as_u16(), 404);
42 /// assert!(StatusCode::OK.is_success());
43 /// ```
44 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
45 pub struct StatusCode(NonZeroU16);
46 
47 /// A possible error value when converting a `StatusCode` from a `u16` or `&str`
48 ///
49 /// This error indicates that the supplied input was not a valid number, was less
50 /// than 100, or was greater than 999.
51 pub struct InvalidStatusCode {
52     _priv: (),
53 }
54 
55 impl StatusCode {
56     /// Converts a u16 to a status code.
57     ///
58     /// The function validates the correctness of the supplied u16. It must be
59     /// greater or equal to 100 and less than 1000.
60     ///
61     /// # Example
62     ///
63     /// ```
64     /// use http::StatusCode;
65     ///
66     /// let ok = StatusCode::from_u16(200).unwrap();
67     /// assert_eq!(ok, StatusCode::OK);
68     ///
69     /// let err = StatusCode::from_u16(99);
70     /// assert!(err.is_err());
71     /// ```
72     #[inline]
from_u16(src: u16) -> Result<StatusCode, InvalidStatusCode>73     pub fn from_u16(src: u16) -> Result<StatusCode, InvalidStatusCode> {
74         if src < 100 || src >= 1000 {
75             return Err(InvalidStatusCode::new());
76         }
77 
78         NonZeroU16::new(src)
79             .map(StatusCode)
80             .ok_or_else(InvalidStatusCode::new)
81     }
82 
83     /// Converts a &[u8] to a status code
from_bytes(src: &[u8]) -> Result<StatusCode, InvalidStatusCode>84     pub fn from_bytes(src: &[u8]) -> Result<StatusCode, InvalidStatusCode> {
85         if src.len() != 3 {
86             return Err(InvalidStatusCode::new());
87         }
88 
89         let a = src[0].wrapping_sub(b'0') as u16;
90         let b = src[1].wrapping_sub(b'0') as u16;
91         let c = src[2].wrapping_sub(b'0') as u16;
92 
93         if a == 0 || a > 9 || b > 9 || c > 9 {
94             return Err(InvalidStatusCode::new());
95         }
96 
97         let status = (a * 100) + (b * 10) + c;
98         NonZeroU16::new(status)
99             .map(StatusCode)
100             .ok_or_else(InvalidStatusCode::new)
101     }
102 
103     /// Returns the `u16` corresponding to this `StatusCode`.
104     ///
105     /// # Note
106     ///
107     /// This is the same as the `From<StatusCode>` implementation, but
108     /// included as an inherent method because that implementation doesn't
109     /// appear in rustdocs, as well as a way to force the type instead of
110     /// relying on inference.
111     ///
112     /// # Example
113     ///
114     /// ```
115     /// let status = http::StatusCode::OK;
116     /// assert_eq!(status.as_u16(), 200);
117     /// ```
118     #[inline]
as_u16(&self) -> u16119     pub fn as_u16(&self) -> u16 {
120         (*self).into()
121     }
122 
123     /// Returns a &str representation of the `StatusCode`
124     ///
125     /// The return value only includes a numerical representation of the
126     /// status code. The canonical reason is not included.
127     ///
128     /// # Example
129     ///
130     /// ```
131     /// let status = http::StatusCode::OK;
132     /// assert_eq!(status.as_str(), "200");
133     /// ```
134     #[inline]
as_str(&self) -> &str135     pub fn as_str(&self) -> &str {
136         let offset = (self.0.get() - 100) as usize;
137         let offset = offset * 3;
138 
139         // Invariant: self has checked range [100, 999] and CODE_DIGITS is
140         // ASCII-only, of length 900 * 3 = 2700 bytes
141 
142         #[cfg(debug_assertions)]
143         { &CODE_DIGITS[offset..offset+3] }
144 
145         #[cfg(not(debug_assertions))]
146         unsafe { CODE_DIGITS.get_unchecked(offset..offset+3) }
147     }
148 
149     /// Get the standardised `reason-phrase` for this status code.
150     ///
151     /// This is mostly here for servers writing responses, but could potentially have application
152     /// at other times.
153     ///
154     /// The reason phrase is defined as being exclusively for human readers. You should avoid
155     /// deriving any meaning from it at all costs.
156     ///
157     /// Bear in mind also that in HTTP/2.0 and HTTP/3.0 the reason phrase is abolished from
158     /// transmission, and so this canonical reason phrase really is the only reason phrase you’ll
159     /// find.
160     ///
161     /// # Example
162     ///
163     /// ```
164     /// let status = http::StatusCode::OK;
165     /// assert_eq!(status.canonical_reason(), Some("OK"));
166     /// ```
canonical_reason(&self) -> Option<&'static str>167     pub fn canonical_reason(&self) -> Option<&'static str> {
168         canonical_reason(self.0.get())
169     }
170 
171     /// Check if status is within 100-199.
172     #[inline]
is_informational(&self) -> bool173     pub fn is_informational(&self) -> bool {
174         200 > self.0.get() && self.0.get() >= 100
175     }
176 
177     /// Check if status is within 200-299.
178     #[inline]
is_success(&self) -> bool179     pub fn is_success(&self) -> bool {
180         300 > self.0.get() && self.0.get() >= 200
181     }
182 
183     /// Check if status is within 300-399.
184     #[inline]
is_redirection(&self) -> bool185     pub fn is_redirection(&self) -> bool {
186         400 > self.0.get() && self.0.get() >= 300
187     }
188 
189     /// Check if status is within 400-499.
190     #[inline]
is_client_error(&self) -> bool191     pub fn is_client_error(&self) -> bool {
192         500 > self.0.get() && self.0.get() >= 400
193     }
194 
195     /// Check if status is within 500-599.
196     #[inline]
is_server_error(&self) -> bool197     pub fn is_server_error(&self) -> bool {
198         600 > self.0.get() && self.0.get() >= 500
199     }
200 }
201 
202 impl fmt::Debug for StatusCode {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result203     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
204         fmt::Debug::fmt(&self.0, f)
205     }
206 }
207 
208 /// Formats the status code, *including* the canonical reason.
209 ///
210 /// # Example
211 ///
212 /// ```
213 /// # use http::StatusCode;
214 /// assert_eq!(format!("{}", StatusCode::OK), "200 OK");
215 /// ```
216 impl fmt::Display for StatusCode {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result217     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
218         write!(
219             f,
220             "{} {}",
221             u16::from(*self),
222             self.canonical_reason().unwrap_or("<unknown status code>")
223         )
224     }
225 }
226 
227 impl Default for StatusCode {
228     #[inline]
default() -> StatusCode229     fn default() -> StatusCode {
230         StatusCode::OK
231     }
232 }
233 
234 impl PartialEq<u16> for StatusCode {
235     #[inline]
eq(&self, other: &u16) -> bool236     fn eq(&self, other: &u16) -> bool {
237         self.as_u16() == *other
238     }
239 }
240 
241 impl PartialEq<StatusCode> for u16 {
242     #[inline]
eq(&self, other: &StatusCode) -> bool243     fn eq(&self, other: &StatusCode) -> bool {
244         *self == other.as_u16()
245     }
246 }
247 
248 impl From<StatusCode> for u16 {
249     #[inline]
from(status: StatusCode) -> u16250     fn from(status: StatusCode) -> u16 {
251         status.0.get()
252     }
253 }
254 
255 impl FromStr for StatusCode {
256     type Err = InvalidStatusCode;
257 
from_str(s: &str) -> Result<StatusCode, InvalidStatusCode>258     fn from_str(s: &str) -> Result<StatusCode, InvalidStatusCode> {
259         StatusCode::from_bytes(s.as_ref())
260     }
261 }
262 
263 impl<'a> From<&'a StatusCode> for StatusCode {
264     #[inline]
from(t: &'a StatusCode) -> Self265     fn from(t: &'a StatusCode) -> Self {
266         t.clone()
267     }
268 }
269 
270 impl<'a> TryFrom<&'a [u8]> for StatusCode {
271     type Error = InvalidStatusCode;
272 
273     #[inline]
try_from(t: &'a [u8]) -> Result<Self, Self::Error>274     fn try_from(t: &'a [u8]) -> Result<Self, Self::Error> {
275         StatusCode::from_bytes(t)
276     }
277 }
278 
279 impl<'a> TryFrom<&'a str> for StatusCode {
280     type Error = InvalidStatusCode;
281 
282     #[inline]
try_from(t: &'a str) -> Result<Self, Self::Error>283     fn try_from(t: &'a str) -> Result<Self, Self::Error> {
284         t.parse()
285     }
286 }
287 
288 impl TryFrom<u16> for StatusCode {
289     type Error = InvalidStatusCode;
290 
291     #[inline]
try_from(t: u16) -> Result<Self, Self::Error>292     fn try_from(t: u16) -> Result<Self, Self::Error> {
293         StatusCode::from_u16(t)
294     }
295 }
296 
297 macro_rules! status_codes {
298     (
299         $(
300             $(#[$docs:meta])*
301             ($num:expr, $konst:ident, $phrase:expr);
302         )+
303     ) => {
304         impl StatusCode {
305         $(
306             $(#[$docs])*
307             pub const $konst: StatusCode = StatusCode(unsafe { NonZeroU16::new_unchecked($num) });
308         )+
309 
310         }
311 
312         fn canonical_reason(num: u16) -> Option<&'static str> {
313             match num {
314                 $(
315                 $num => Some($phrase),
316                 )+
317                 _ => None
318             }
319         }
320     }
321 }
322 
323 status_codes! {
324     /// 100 Continue
325     /// [[RFC7231, Section 6.2.1](https://tools.ietf.org/html/rfc7231#section-6.2.1)]
326     (100, CONTINUE, "Continue");
327     /// 101 Switching Protocols
328     /// [[RFC7231, Section 6.2.2](https://tools.ietf.org/html/rfc7231#section-6.2.2)]
329     (101, SWITCHING_PROTOCOLS, "Switching Protocols");
330     /// 102 Processing
331     /// [[RFC2518](https://tools.ietf.org/html/rfc2518)]
332     (102, PROCESSING, "Processing");
333 
334     /// 200 OK
335     /// [[RFC7231, Section 6.3.1](https://tools.ietf.org/html/rfc7231#section-6.3.1)]
336     (200, OK, "OK");
337     /// 201 Created
338     /// [[RFC7231, Section 6.3.2](https://tools.ietf.org/html/rfc7231#section-6.3.2)]
339     (201, CREATED, "Created");
340     /// 202 Accepted
341     /// [[RFC7231, Section 6.3.3](https://tools.ietf.org/html/rfc7231#section-6.3.3)]
342     (202, ACCEPTED, "Accepted");
343     /// 203 Non-Authoritative Information
344     /// [[RFC7231, Section 6.3.4](https://tools.ietf.org/html/rfc7231#section-6.3.4)]
345     (203, NON_AUTHORITATIVE_INFORMATION, "Non Authoritative Information");
346     /// 204 No Content
347     /// [[RFC7231, Section 6.3.5](https://tools.ietf.org/html/rfc7231#section-6.3.5)]
348     (204, NO_CONTENT, "No Content");
349     /// 205 Reset Content
350     /// [[RFC7231, Section 6.3.6](https://tools.ietf.org/html/rfc7231#section-6.3.6)]
351     (205, RESET_CONTENT, "Reset Content");
352     /// 206 Partial Content
353     /// [[RFC7233, Section 4.1](https://tools.ietf.org/html/rfc7233#section-4.1)]
354     (206, PARTIAL_CONTENT, "Partial Content");
355     /// 207 Multi-Status
356     /// [[RFC4918](https://tools.ietf.org/html/rfc4918)]
357     (207, MULTI_STATUS, "Multi-Status");
358     /// 208 Already Reported
359     /// [[RFC5842](https://tools.ietf.org/html/rfc5842)]
360     (208, ALREADY_REPORTED, "Already Reported");
361 
362     /// 226 IM Used
363     /// [[RFC3229](https://tools.ietf.org/html/rfc3229)]
364     (226, IM_USED, "IM Used");
365 
366     /// 300 Multiple Choices
367     /// [[RFC7231, Section 6.4.1](https://tools.ietf.org/html/rfc7231#section-6.4.1)]
368     (300, MULTIPLE_CHOICES, "Multiple Choices");
369     /// 301 Moved Permanently
370     /// [[RFC7231, Section 6.4.2](https://tools.ietf.org/html/rfc7231#section-6.4.2)]
371     (301, MOVED_PERMANENTLY, "Moved Permanently");
372     /// 302 Found
373     /// [[RFC7231, Section 6.4.3](https://tools.ietf.org/html/rfc7231#section-6.4.3)]
374     (302, FOUND, "Found");
375     /// 303 See Other
376     /// [[RFC7231, Section 6.4.4](https://tools.ietf.org/html/rfc7231#section-6.4.4)]
377     (303, SEE_OTHER, "See Other");
378     /// 304 Not Modified
379     /// [[RFC7232, Section 4.1](https://tools.ietf.org/html/rfc7232#section-4.1)]
380     (304, NOT_MODIFIED, "Not Modified");
381     /// 305 Use Proxy
382     /// [[RFC7231, Section 6.4.5](https://tools.ietf.org/html/rfc7231#section-6.4.5)]
383     (305, USE_PROXY, "Use Proxy");
384     /// 307 Temporary Redirect
385     /// [[RFC7231, Section 6.4.7](https://tools.ietf.org/html/rfc7231#section-6.4.7)]
386     (307, TEMPORARY_REDIRECT, "Temporary Redirect");
387     /// 308 Permanent Redirect
388     /// [[RFC7238](https://tools.ietf.org/html/rfc7238)]
389     (308, PERMANENT_REDIRECT, "Permanent Redirect");
390 
391     /// 400 Bad Request
392     /// [[RFC7231, Section 6.5.1](https://tools.ietf.org/html/rfc7231#section-6.5.1)]
393     (400, BAD_REQUEST, "Bad Request");
394     /// 401 Unauthorized
395     /// [[RFC7235, Section 3.1](https://tools.ietf.org/html/rfc7235#section-3.1)]
396     (401, UNAUTHORIZED, "Unauthorized");
397     /// 402 Payment Required
398     /// [[RFC7231, Section 6.5.2](https://tools.ietf.org/html/rfc7231#section-6.5.2)]
399     (402, PAYMENT_REQUIRED, "Payment Required");
400     /// 403 Forbidden
401     /// [[RFC7231, Section 6.5.3](https://tools.ietf.org/html/rfc7231#section-6.5.3)]
402     (403, FORBIDDEN, "Forbidden");
403     /// 404 Not Found
404     /// [[RFC7231, Section 6.5.4](https://tools.ietf.org/html/rfc7231#section-6.5.4)]
405     (404, NOT_FOUND, "Not Found");
406     /// 405 Method Not Allowed
407     /// [[RFC7231, Section 6.5.5](https://tools.ietf.org/html/rfc7231#section-6.5.5)]
408     (405, METHOD_NOT_ALLOWED, "Method Not Allowed");
409     /// 406 Not Acceptable
410     /// [[RFC7231, Section 6.5.6](https://tools.ietf.org/html/rfc7231#section-6.5.6)]
411     (406, NOT_ACCEPTABLE, "Not Acceptable");
412     /// 407 Proxy Authentication Required
413     /// [[RFC7235, Section 3.2](https://tools.ietf.org/html/rfc7235#section-3.2)]
414     (407, PROXY_AUTHENTICATION_REQUIRED, "Proxy Authentication Required");
415     /// 408 Request Timeout
416     /// [[RFC7231, Section 6.5.7](https://tools.ietf.org/html/rfc7231#section-6.5.7)]
417     (408, REQUEST_TIMEOUT, "Request Timeout");
418     /// 409 Conflict
419     /// [[RFC7231, Section 6.5.8](https://tools.ietf.org/html/rfc7231#section-6.5.8)]
420     (409, CONFLICT, "Conflict");
421     /// 410 Gone
422     /// [[RFC7231, Section 6.5.9](https://tools.ietf.org/html/rfc7231#section-6.5.9)]
423     (410, GONE, "Gone");
424     /// 411 Length Required
425     /// [[RFC7231, Section 6.5.10](https://tools.ietf.org/html/rfc7231#section-6.5.10)]
426     (411, LENGTH_REQUIRED, "Length Required");
427     /// 412 Precondition Failed
428     /// [[RFC7232, Section 4.2](https://tools.ietf.org/html/rfc7232#section-4.2)]
429     (412, PRECONDITION_FAILED, "Precondition Failed");
430     /// 413 Payload Too Large
431     /// [[RFC7231, Section 6.5.11](https://tools.ietf.org/html/rfc7231#section-6.5.11)]
432     (413, PAYLOAD_TOO_LARGE, "Payload Too Large");
433     /// 414 URI Too Long
434     /// [[RFC7231, Section 6.5.12](https://tools.ietf.org/html/rfc7231#section-6.5.12)]
435     (414, URI_TOO_LONG, "URI Too Long");
436     /// 415 Unsupported Media Type
437     /// [[RFC7231, Section 6.5.13](https://tools.ietf.org/html/rfc7231#section-6.5.13)]
438     (415, UNSUPPORTED_MEDIA_TYPE, "Unsupported Media Type");
439     /// 416 Range Not Satisfiable
440     /// [[RFC7233, Section 4.4](https://tools.ietf.org/html/rfc7233#section-4.4)]
441     (416, RANGE_NOT_SATISFIABLE, "Range Not Satisfiable");
442     /// 417 Expectation Failed
443     /// [[RFC7231, Section 6.5.14](https://tools.ietf.org/html/rfc7231#section-6.5.14)]
444     (417, EXPECTATION_FAILED, "Expectation Failed");
445     /// 418 I'm a teapot
446     /// [curiously not registered by IANA but [RFC2324](https://tools.ietf.org/html/rfc2324)]
447     (418, IM_A_TEAPOT, "I'm a teapot");
448 
449     /// 421 Misdirected Request
450     /// [RFC7540, Section 9.1.2](http://tools.ietf.org/html/rfc7540#section-9.1.2)
451     (421, MISDIRECTED_REQUEST, "Misdirected Request");
452     /// 422 Unprocessable Entity
453     /// [[RFC4918](https://tools.ietf.org/html/rfc4918)]
454     (422, UNPROCESSABLE_ENTITY, "Unprocessable Entity");
455     /// 423 Locked
456     /// [[RFC4918](https://tools.ietf.org/html/rfc4918)]
457     (423, LOCKED, "Locked");
458     /// 424 Failed Dependency
459     /// [[RFC4918](https://tools.ietf.org/html/rfc4918)]
460     (424, FAILED_DEPENDENCY, "Failed Dependency");
461 
462     /// 426 Upgrade Required
463     /// [[RFC7231, Section 6.5.15](https://tools.ietf.org/html/rfc7231#section-6.5.15)]
464     (426, UPGRADE_REQUIRED, "Upgrade Required");
465 
466     /// 428 Precondition Required
467     /// [[RFC6585](https://tools.ietf.org/html/rfc6585)]
468     (428, PRECONDITION_REQUIRED, "Precondition Required");
469     /// 429 Too Many Requests
470     /// [[RFC6585](https://tools.ietf.org/html/rfc6585)]
471     (429, TOO_MANY_REQUESTS, "Too Many Requests");
472 
473     /// 431 Request Header Fields Too Large
474     /// [[RFC6585](https://tools.ietf.org/html/rfc6585)]
475     (431, REQUEST_HEADER_FIELDS_TOO_LARGE, "Request Header Fields Too Large");
476 
477     /// 451 Unavailable For Legal Reasons
478     /// [[RFC7725](http://tools.ietf.org/html/rfc7725)]
479     (451, UNAVAILABLE_FOR_LEGAL_REASONS, "Unavailable For Legal Reasons");
480 
481     /// 500 Internal Server Error
482     /// [[RFC7231, Section 6.6.1](https://tools.ietf.org/html/rfc7231#section-6.6.1)]
483     (500, INTERNAL_SERVER_ERROR, "Internal Server Error");
484     /// 501 Not Implemented
485     /// [[RFC7231, Section 6.6.2](https://tools.ietf.org/html/rfc7231#section-6.6.2)]
486     (501, NOT_IMPLEMENTED, "Not Implemented");
487     /// 502 Bad Gateway
488     /// [[RFC7231, Section 6.6.3](https://tools.ietf.org/html/rfc7231#section-6.6.3)]
489     (502, BAD_GATEWAY, "Bad Gateway");
490     /// 503 Service Unavailable
491     /// [[RFC7231, Section 6.6.4](https://tools.ietf.org/html/rfc7231#section-6.6.4)]
492     (503, SERVICE_UNAVAILABLE, "Service Unavailable");
493     /// 504 Gateway Timeout
494     /// [[RFC7231, Section 6.6.5](https://tools.ietf.org/html/rfc7231#section-6.6.5)]
495     (504, GATEWAY_TIMEOUT, "Gateway Timeout");
496     /// 505 HTTP Version Not Supported
497     /// [[RFC7231, Section 6.6.6](https://tools.ietf.org/html/rfc7231#section-6.6.6)]
498     (505, HTTP_VERSION_NOT_SUPPORTED, "HTTP Version Not Supported");
499     /// 506 Variant Also Negotiates
500     /// [[RFC2295](https://tools.ietf.org/html/rfc2295)]
501     (506, VARIANT_ALSO_NEGOTIATES, "Variant Also Negotiates");
502     /// 507 Insufficient Storage
503     /// [[RFC4918](https://tools.ietf.org/html/rfc4918)]
504     (507, INSUFFICIENT_STORAGE, "Insufficient Storage");
505     /// 508 Loop Detected
506     /// [[RFC5842](https://tools.ietf.org/html/rfc5842)]
507     (508, LOOP_DETECTED, "Loop Detected");
508 
509     /// 510 Not Extended
510     /// [[RFC2774](https://tools.ietf.org/html/rfc2774)]
511     (510, NOT_EXTENDED, "Not Extended");
512     /// 511 Network Authentication Required
513     /// [[RFC6585](https://tools.ietf.org/html/rfc6585)]
514     (511, NETWORK_AUTHENTICATION_REQUIRED, "Network Authentication Required");
515 }
516 
517 impl InvalidStatusCode {
new() -> InvalidStatusCode518     fn new() -> InvalidStatusCode {
519         InvalidStatusCode {
520             _priv: (),
521         }
522     }
523 }
524 
525 impl fmt::Debug for InvalidStatusCode {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result526     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
527         f.debug_struct("InvalidStatusCode")
528             // skip _priv noise
529             .finish()
530     }
531 }
532 
533 impl fmt::Display for InvalidStatusCode {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result534     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
535         f.write_str("invalid status code")
536     }
537 }
538 
539 impl Error for InvalidStatusCode {}
540 
541 // A string of packed 3-ASCII-digit status code values for the supported range
542 // of [100, 999] (900 codes, 2700 bytes).
543 const CODE_DIGITS: &'static str = "\
544 100101102103104105106107108109110111112113114115116117118119\
545 120121122123124125126127128129130131132133134135136137138139\
546 140141142143144145146147148149150151152153154155156157158159\
547 160161162163164165166167168169170171172173174175176177178179\
548 180181182183184185186187188189190191192193194195196197198199\
549 200201202203204205206207208209210211212213214215216217218219\
550 220221222223224225226227228229230231232233234235236237238239\
551 240241242243244245246247248249250251252253254255256257258259\
552 260261262263264265266267268269270271272273274275276277278279\
553 280281282283284285286287288289290291292293294295296297298299\
554 300301302303304305306307308309310311312313314315316317318319\
555 320321322323324325326327328329330331332333334335336337338339\
556 340341342343344345346347348349350351352353354355356357358359\
557 360361362363364365366367368369370371372373374375376377378379\
558 380381382383384385386387388389390391392393394395396397398399\
559 400401402403404405406407408409410411412413414415416417418419\
560 420421422423424425426427428429430431432433434435436437438439\
561 440441442443444445446447448449450451452453454455456457458459\
562 460461462463464465466467468469470471472473474475476477478479\
563 480481482483484485486487488489490491492493494495496497498499\
564 500501502503504505506507508509510511512513514515516517518519\
565 520521522523524525526527528529530531532533534535536537538539\
566 540541542543544545546547548549550551552553554555556557558559\
567 560561562563564565566567568569570571572573574575576577578579\
568 580581582583584585586587588589590591592593594595596597598599\
569 600601602603604605606607608609610611612613614615616617618619\
570 620621622623624625626627628629630631632633634635636637638639\
571 640641642643644645646647648649650651652653654655656657658659\
572 660661662663664665666667668669670671672673674675676677678679\
573 680681682683684685686687688689690691692693694695696697698699\
574 700701702703704705706707708709710711712713714715716717718719\
575 720721722723724725726727728729730731732733734735736737738739\
576 740741742743744745746747748749750751752753754755756757758759\
577 760761762763764765766767768769770771772773774775776777778779\
578 780781782783784785786787788789790791792793794795796797798799\
579 800801802803804805806807808809810811812813814815816817818819\
580 820821822823824825826827828829830831832833834835836837838839\
581 840841842843844845846847848849850851852853854855856857858859\
582 860861862863864865866867868869870871872873874875876877878879\
583 880881882883884885886887888889890891892893894895896897898899\
584 900901902903904905906907908909910911912913914915916917918919\
585 920921922923924925926927928929930931932933934935936937938939\
586 940941942943944945946947948949950951952953954955956957958959\
587 960961962963964965966967968969970971972973974975976977978979\
588 980981982983984985986987988989990991992993994995996997998999";
589