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