Coverage Report

Created: 2025-11-09 06:44

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/http/src/status.rs
Line
Count
Source
1
//! HTTP status codes
2
//!
3
//! This module contains HTTP-status code related structs and 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::error::Error;
19
use std::fmt;
20
use std::num::NonZeroU16;
21
use std::str::FromStr;
22
23
/// An HTTP status code (`status-code` in RFC 9110 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]
73
    pub const fn from_u16(src: u16) -> Result<StatusCode, InvalidStatusCode> {
74
        if let 100..=999 = src {
75
            if let Some(code) = NonZeroU16::new(src) {
76
                return Ok(StatusCode(code));
77
            }
78
        }
79
        Err(InvalidStatusCode::new())
80
    }
81
82
    /// Converts a `&[u8]` to a status code.
83
5.80k
    pub fn from_bytes(src: &[u8]) -> Result<StatusCode, InvalidStatusCode> {
84
5.80k
        if src.len() != 3 {
85
5.77k
            return Err(InvalidStatusCode::new());
86
23
        }
87
88
23
        let a = src[0].wrapping_sub(b'0') as u16;
89
23
        let b = src[1].wrapping_sub(b'0') as u16;
90
23
        let c = src[2].wrapping_sub(b'0') as u16;
91
92
23
        if a == 0 || a > 9 || b > 9 || c > 9 {
93
20
            return Err(InvalidStatusCode::new());
94
3
        }
95
96
3
        let status = (a * 100) + (b * 10) + c;
97
3
        NonZeroU16::new(status)
98
3
            .map(StatusCode)
99
3
            .ok_or_else(InvalidStatusCode::new)
100
5.80k
    }
101
102
    /// Returns the `u16` corresponding to this `StatusCode`.
103
    ///
104
    /// # Note
105
    ///
106
    /// This is the same as the `From<StatusCode>` implementation, but
107
    /// included as an inherent method because that implementation doesn't
108
    /// appear in rustdocs, as well as a way to force the type instead of
109
    /// relying on inference.
110
    ///
111
    /// # Example
112
    ///
113
    /// ```
114
    /// let status = http::StatusCode::OK;
115
    /// assert_eq!(status.as_u16(), 200);
116
    /// ```
117
    #[inline]
118
    pub const fn as_u16(&self) -> u16 {
119
        self.0.get()
120
    }
121
122
    /// Returns a &str representation of the `StatusCode`
123
    ///
124
    /// The return value only includes a numerical representation of the
125
    /// status code. The canonical reason is not included.
126
    ///
127
    /// # Example
128
    ///
129
    /// ```
130
    /// let status = http::StatusCode::OK;
131
    /// assert_eq!(status.as_str(), "200");
132
    /// ```
133
    #[inline]
134
    pub fn as_str(&self) -> &str {
135
        let offset = (self.0.get() - 100) as usize;
136
        let offset = offset * 3;
137
138
        // Invariant: self has checked range [100, 999] and CODE_DIGITS is
139
        // ASCII-only, of length 900 * 3 = 2700 bytes
140
141
        #[cfg(debug_assertions)]
142
        {
143
            &CODE_DIGITS[offset..offset + 3]
144
        }
145
146
        #[cfg(not(debug_assertions))]
147
        unsafe {
148
            CODE_DIGITS.get_unchecked(offset..offset + 3)
149
        }
150
    }
151
152
    /// Get the standardised `reason-phrase` for this status code.
153
    ///
154
    /// This is mostly here for servers writing responses, but could potentially have application
155
    /// at other times.
156
    ///
157
    /// The reason phrase is defined as being exclusively for human readers. You should avoid
158
    /// deriving any meaning from it at all costs.
159
    ///
160
    /// Bear in mind also that in HTTP/2.0 and HTTP/3.0 the reason phrase is abolished from
161
    /// transmission, and so this canonical reason phrase really is the only reason phrase you’ll
162
    /// find.
163
    ///
164
    /// # Example
165
    ///
166
    /// ```
167
    /// let status = http::StatusCode::OK;
168
    /// assert_eq!(status.canonical_reason(), Some("OK"));
169
    /// ```
170
0
    pub fn canonical_reason(&self) -> Option<&'static str> {
171
0
        canonical_reason(self.0.get())
172
0
    }
173
174
    /// Check if status is within 100-199.
175
    #[inline]
176
    pub fn is_informational(&self) -> bool {
177
        (100..200).contains(&self.0.get())
178
    }
179
180
    /// Check if status is within 200-299.
181
    #[inline]
182
    pub fn is_success(&self) -> bool {
183
        (200..300).contains(&self.0.get())
184
    }
185
186
    /// Check if status is within 300-399.
187
    #[inline]
188
    pub fn is_redirection(&self) -> bool {
189
        (300..400).contains(&self.0.get())
190
    }
191
192
    /// Check if status is within 400-499.
193
    #[inline]
194
    pub fn is_client_error(&self) -> bool {
195
        (400..500).contains(&self.0.get())
196
    }
197
198
    /// Check if status is within 500-599.
199
    #[inline]
200
    pub fn is_server_error(&self) -> bool {
201
        (500..600).contains(&self.0.get())
202
    }
203
}
204
205
impl fmt::Debug for StatusCode {
206
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
207
0
        fmt::Debug::fmt(&self.0, f)
208
0
    }
209
}
210
211
/// Formats the status code, *including* the canonical reason.
212
///
213
/// # Example
214
///
215
/// ```
216
/// # use http::StatusCode;
217
/// assert_eq!(format!("{}", StatusCode::OK), "200 OK");
218
/// ```
219
impl fmt::Display for StatusCode {
220
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
221
0
        write!(
222
0
            f,
223
0
            "{} {}",
224
0
            u16::from(*self),
225
0
            self.canonical_reason().unwrap_or("<unknown status code>")
226
        )
227
0
    }
228
}
229
230
impl Default for StatusCode {
231
    #[inline]
232
5.80k
    fn default() -> StatusCode {
233
5.80k
        StatusCode::OK
234
5.80k
    }
235
}
236
237
impl PartialEq<u16> for StatusCode {
238
    #[inline]
239
    fn eq(&self, other: &u16) -> bool {
240
        self.as_u16() == *other
241
    }
242
}
243
244
impl PartialEq<StatusCode> for u16 {
245
    #[inline]
246
    fn eq(&self, other: &StatusCode) -> bool {
247
        *self == other.as_u16()
248
    }
249
}
250
251
impl From<StatusCode> for u16 {
252
    #[inline]
253
0
    fn from(status: StatusCode) -> u16 {
254
0
        status.0.get()
255
0
    }
256
}
257
258
impl FromStr for StatusCode {
259
    type Err = InvalidStatusCode;
260
261
0
    fn from_str(s: &str) -> Result<StatusCode, InvalidStatusCode> {
262
0
        StatusCode::from_bytes(s.as_ref())
263
0
    }
264
}
265
266
impl<'a> From<&'a StatusCode> for StatusCode {
267
    #[inline]
268
    fn from(t: &'a StatusCode) -> Self {
269
        t.to_owned()
270
    }
271
}
272
273
impl<'a> TryFrom<&'a [u8]> for StatusCode {
274
    type Error = InvalidStatusCode;
275
276
    #[inline]
277
    fn try_from(t: &'a [u8]) -> Result<Self, Self::Error> {
278
        StatusCode::from_bytes(t)
279
    }
280
}
281
282
impl<'a> TryFrom<&'a str> for StatusCode {
283
    type Error = InvalidStatusCode;
284
285
    #[inline]
286
    fn try_from(t: &'a str) -> Result<Self, Self::Error> {
287
        t.parse()
288
    }
289
}
290
291
impl TryFrom<u16> for StatusCode {
292
    type Error = InvalidStatusCode;
293
294
    #[inline]
295
    fn try_from(t: u16) -> Result<Self, Self::Error> {
296
        StatusCode::from_u16(t)
297
    }
298
}
299
300
macro_rules! status_codes {
301
    (
302
        $(
303
            $(#[$docs:meta])*
304
            ($num:expr, $konst:ident, $phrase:expr);
305
        )+
306
    ) => {
307
        impl StatusCode {
308
        $(
309
            $(#[$docs])*
310
            pub const $konst: StatusCode = StatusCode(unsafe { NonZeroU16::new_unchecked($num) });
311
        )+
312
313
        }
314
315
0
        fn canonical_reason(num: u16) -> Option<&'static str> {
316
0
            match num {
317
                $(
318
0
                $num => Some($phrase),
319
                )+
320
0
                _ => None
321
            }
322
0
        }
323
    }
324
}
325
326
status_codes! {
327
    /// 100 Continue
328
    /// [[RFC9110, Section 15.2.1](https://datatracker.ietf.org/doc/html/rfc9110#section-15.2.1)]
329
    (100, CONTINUE, "Continue");
330
    /// 101 Switching Protocols
331
    /// [[RFC9110, Section 15.2.2](https://datatracker.ietf.org/doc/html/rfc9110#section-15.2.2)]
332
    (101, SWITCHING_PROTOCOLS, "Switching Protocols");
333
    /// 102 Processing
334
    /// [[RFC2518, Section 10.1](https://datatracker.ietf.org/doc/html/rfc2518#section-10.1)]
335
    (102, PROCESSING, "Processing");
336
337
    /// 200 OK
338
    /// [[RFC9110, Section 15.3.1](https://datatracker.ietf.org/doc/html/rfc9110#section-15.3.1)]
339
    (200, OK, "OK");
340
    /// 201 Created
341
    /// [[RFC9110, Section 15.3.2](https://datatracker.ietf.org/doc/html/rfc9110#section-15.3.2)]
342
    (201, CREATED, "Created");
343
    /// 202 Accepted
344
    /// [[RFC9110, Section 15.3.3](https://datatracker.ietf.org/doc/html/rfc9110#section-15.3.3)]
345
    (202, ACCEPTED, "Accepted");
346
    /// 203 Non-Authoritative Information
347
    /// [[RFC9110, Section 15.3.4](https://datatracker.ietf.org/doc/html/rfc9110#section-15.3.4)]
348
    (203, NON_AUTHORITATIVE_INFORMATION, "Non Authoritative Information");
349
    /// 204 No Content
350
    /// [[RFC9110, Section 15.3.5](https://datatracker.ietf.org/doc/html/rfc9110#section-15.3.5)]
351
    (204, NO_CONTENT, "No Content");
352
    /// 205 Reset Content
353
    /// [[RFC9110, Section 15.3.6](https://datatracker.ietf.org/doc/html/rfc9110#section-15.3.6)]
354
    (205, RESET_CONTENT, "Reset Content");
355
    /// 206 Partial Content
356
    /// [[RFC9110, Section 15.3.7](https://datatracker.ietf.org/doc/html/rfc9110#section-15.3.7)]
357
    (206, PARTIAL_CONTENT, "Partial Content");
358
    /// 207 Multi-Status
359
    /// [[RFC4918, Section 11.1](https://datatracker.ietf.org/doc/html/rfc4918#section-11.1)]
360
    (207, MULTI_STATUS, "Multi-Status");
361
    /// 208 Already Reported
362
    /// [[RFC5842, Section 7.1](https://datatracker.ietf.org/doc/html/rfc5842#section-7.1)]
363
    (208, ALREADY_REPORTED, "Already Reported");
364
365
    /// 226 IM Used
366
    /// [[RFC3229, Section 10.4.1](https://datatracker.ietf.org/doc/html/rfc3229#section-10.4.1)]
367
    (226, IM_USED, "IM Used");
368
369
    /// 300 Multiple Choices
370
    /// [[RFC9110, Section 15.4.1](https://datatracker.ietf.org/doc/html/rfc9110#section-15.4.1)]
371
    (300, MULTIPLE_CHOICES, "Multiple Choices");
372
    /// 301 Moved Permanently
373
    /// [[RFC9110, Section 15.4.2](https://datatracker.ietf.org/doc/html/rfc9110#section-15.4.2)]
374
    (301, MOVED_PERMANENTLY, "Moved Permanently");
375
    /// 302 Found
376
    /// [[RFC9110, Section 15.4.3](https://datatracker.ietf.org/doc/html/rfc9110#section-15.4.3)]
377
    (302, FOUND, "Found");
378
    /// 303 See Other
379
    /// [[RFC9110, Section 15.4.4](https://datatracker.ietf.org/doc/html/rfc9110#section-15.4.4)]
380
    (303, SEE_OTHER, "See Other");
381
    /// 304 Not Modified
382
    /// [[RFC9110, Section 15.4.5](https://datatracker.ietf.org/doc/html/rfc9110#section-15.4.5)]
383
    (304, NOT_MODIFIED, "Not Modified");
384
    /// 305 Use Proxy
385
    /// [[RFC9110, Section 15.4.6](https://datatracker.ietf.org/doc/html/rfc9110#section-15.4.6)]
386
    (305, USE_PROXY, "Use Proxy");
387
    /// 307 Temporary Redirect
388
    /// [[RFC9110, Section 15.4.7](https://datatracker.ietf.org/doc/html/rfc9110#section-15.4.7)]
389
    (307, TEMPORARY_REDIRECT, "Temporary Redirect");
390
    /// 308 Permanent Redirect
391
    /// [[RFC9110, Section 15.4.8](https://datatracker.ietf.org/doc/html/rfc9110#section-15.4.8)]
392
    (308, PERMANENT_REDIRECT, "Permanent Redirect");
393
394
    /// 400 Bad Request
395
    /// [[RFC9110, Section 15.5.1](https://datatracker.ietf.org/doc/html/rfc9110#section-15.5.1)]
396
    (400, BAD_REQUEST, "Bad Request");
397
    /// 401 Unauthorized
398
    /// [[RFC9110, Section 15.5.2](https://datatracker.ietf.org/doc/html/rfc9110#section-15.5.2)]
399
    (401, UNAUTHORIZED, "Unauthorized");
400
    /// 402 Payment Required
401
    /// [[RFC9110, Section 15.5.3](https://datatracker.ietf.org/doc/html/rfc9110#section-15.5.3)]
402
    (402, PAYMENT_REQUIRED, "Payment Required");
403
    /// 403 Forbidden
404
    /// [[RFC9110, Section 15.5.4](https://datatracker.ietf.org/doc/html/rfc9110#section-15.5.4)]
405
    (403, FORBIDDEN, "Forbidden");
406
    /// 404 Not Found
407
    /// [[RFC9110, Section 15.5.5](https://datatracker.ietf.org/doc/html/rfc9110#section-15.5.5)]
408
    (404, NOT_FOUND, "Not Found");
409
    /// 405 Method Not Allowed
410
    /// [[RFC9110, Section 15.5.6](https://datatracker.ietf.org/doc/html/rfc9110#section-15.5.6)]
411
    (405, METHOD_NOT_ALLOWED, "Method Not Allowed");
412
    /// 406 Not Acceptable
413
    /// [[RFC9110, Section 15.5.7](https://datatracker.ietf.org/doc/html/rfc9110#section-15.5.7)]
414
    (406, NOT_ACCEPTABLE, "Not Acceptable");
415
    /// 407 Proxy Authentication Required
416
    /// [[RFC9110, Section 15.5.8](https://datatracker.ietf.org/doc/html/rfc9110#section-15.5.8)]
417
    (407, PROXY_AUTHENTICATION_REQUIRED, "Proxy Authentication Required");
418
    /// 408 Request Timeout
419
    /// [[RFC9110, Section 15.5.9](https://datatracker.ietf.org/doc/html/rfc9110#section-15.5.9)]
420
    (408, REQUEST_TIMEOUT, "Request Timeout");
421
    /// 409 Conflict
422
    /// [[RFC9110, Section 15.5.10](https://datatracker.ietf.org/doc/html/rfc9110#section-15.5.10)]
423
    (409, CONFLICT, "Conflict");
424
    /// 410 Gone
425
    /// [[RFC9110, Section 15.5.11](https://datatracker.ietf.org/doc/html/rfc9110#section-15.5.11)]
426
    (410, GONE, "Gone");
427
    /// 411 Length Required
428
    /// [[RFC9110, Section 15.5.12](https://datatracker.ietf.org/doc/html/rfc9110#section-15.5.12)]
429
    (411, LENGTH_REQUIRED, "Length Required");
430
    /// 412 Precondition Failed
431
    /// [[RFC9110, Section 15.5.13](https://datatracker.ietf.org/doc/html/rfc9110#section-15.5.13)]
432
    (412, PRECONDITION_FAILED, "Precondition Failed");
433
    /// 413 Payload Too Large
434
    /// [[RFC9110, Section 15.5.14](https://datatracker.ietf.org/doc/html/rfc9110#section-15.5.14)]
435
    (413, PAYLOAD_TOO_LARGE, "Payload Too Large");
436
    /// 414 URI Too Long
437
    /// [[RFC9110, Section 15.5.15](https://datatracker.ietf.org/doc/html/rfc9110#section-15.5.15)]
438
    (414, URI_TOO_LONG, "URI Too Long");
439
    /// 415 Unsupported Media Type
440
    /// [[RFC9110, Section 15.5.16](https://datatracker.ietf.org/doc/html/rfc9110#section-15.5.16)]
441
    (415, UNSUPPORTED_MEDIA_TYPE, "Unsupported Media Type");
442
    /// 416 Range Not Satisfiable
443
    /// [[RFC9110, Section 15.5.17](https://datatracker.ietf.org/doc/html/rfc9110#section-15.5.17)]
444
    (416, RANGE_NOT_SATISFIABLE, "Range Not Satisfiable");
445
    /// 417 Expectation Failed
446
    /// [[RFC9110, Section 15.5.18](https://datatracker.ietf.org/doc/html/rfc9110#section-15.5.18)]
447
    (417, EXPECTATION_FAILED, "Expectation Failed");
448
    /// 418 I'm a teapot
449
    /// [curiously not registered by IANA but [RFC2324, Section 2.3.2](https://datatracker.ietf.org/doc/html/rfc2324#section-2.3.2)]
450
    (418, IM_A_TEAPOT, "I'm a teapot");
451
452
    /// 421 Misdirected Request
453
    /// [[RFC9110, Section 15.5.20](https://datatracker.ietf.org/doc/html/rfc9110#section-15.5.20)]
454
    (421, MISDIRECTED_REQUEST, "Misdirected Request");
455
    /// 422 Unprocessable Entity
456
    /// [[RFC9110, Section 15.5.21](https://datatracker.ietf.org/doc/html/rfc9110#section-15.5.21)]
457
    (422, UNPROCESSABLE_ENTITY, "Unprocessable Entity");
458
    /// 423 Locked
459
    /// [[RFC4918, Section 11.3](https://datatracker.ietf.org/doc/html/rfc4918#section-11.3)]
460
    (423, LOCKED, "Locked");
461
    /// 424 Failed Dependency
462
    /// [[RFC4918, Section 11.4](https://tools.ietf.org/html/rfc4918#section-11.4)]
463
    (424, FAILED_DEPENDENCY, "Failed Dependency");
464
465
    /// 425 Too early
466
    /// [[RFC8470, Section 5.2](https://httpwg.org/specs/rfc8470.html#status)]
467
    (425, TOO_EARLY, "Too Early");
468
469
    /// 426 Upgrade Required
470
    /// [[RFC9110, Section 15.5.22](https://datatracker.ietf.org/doc/html/rfc9110#section-15.5.22)]
471
    (426, UPGRADE_REQUIRED, "Upgrade Required");
472
473
    /// 428 Precondition Required
474
    /// [[RFC6585, Section 3](https://datatracker.ietf.org/doc/html/rfc6585#section-3)]
475
    (428, PRECONDITION_REQUIRED, "Precondition Required");
476
    /// 429 Too Many Requests
477
    /// [[RFC6585, Section 4](https://datatracker.ietf.org/doc/html/rfc6585#section-4)]
478
    (429, TOO_MANY_REQUESTS, "Too Many Requests");
479
480
    /// 431 Request Header Fields Too Large
481
    /// [[RFC6585, Section 5](https://datatracker.ietf.org/doc/html/rfc6585#section-5)]
482
    (431, REQUEST_HEADER_FIELDS_TOO_LARGE, "Request Header Fields Too Large");
483
484
    /// 451 Unavailable For Legal Reasons
485
    /// [[RFC7725, Section 3](https://tools.ietf.org/html/rfc7725#section-3)]
486
    (451, UNAVAILABLE_FOR_LEGAL_REASONS, "Unavailable For Legal Reasons");
487
488
    /// 500 Internal Server Error
489
    /// [[RFC9110, Section 15.6.1](https://datatracker.ietf.org/doc/html/rfc9110#section-15.6.1)]
490
    (500, INTERNAL_SERVER_ERROR, "Internal Server Error");
491
    /// 501 Not Implemented
492
    /// [[RFC9110, Section 15.6.2](https://datatracker.ietf.org/doc/html/rfc9110#section-15.6.2)]
493
    (501, NOT_IMPLEMENTED, "Not Implemented");
494
    /// 502 Bad Gateway
495
    /// [[RFC9110, Section 15.6.3](https://datatracker.ietf.org/doc/html/rfc9110#section-15.6.3)]
496
    (502, BAD_GATEWAY, "Bad Gateway");
497
    /// 503 Service Unavailable
498
    /// [[RFC9110, Section 15.6.4](https://datatracker.ietf.org/doc/html/rfc9110#section-15.6.4)]
499
    (503, SERVICE_UNAVAILABLE, "Service Unavailable");
500
    /// 504 Gateway Timeout
501
    /// [[RFC9110, Section 15.6.5](https://datatracker.ietf.org/doc/html/rfc9110#section-15.6.5)]
502
    (504, GATEWAY_TIMEOUT, "Gateway Timeout");
503
    /// 505 HTTP Version Not Supported
504
    /// [[RFC9110, Section 15.6.6](https://datatracker.ietf.org/doc/html/rfc9110#section-15.6.6)]
505
    (505, HTTP_VERSION_NOT_SUPPORTED, "HTTP Version Not Supported");
506
    /// 506 Variant Also Negotiates
507
    /// [[RFC2295, Section 8.1](https://datatracker.ietf.org/doc/html/rfc2295#section-8.1)]
508
    (506, VARIANT_ALSO_NEGOTIATES, "Variant Also Negotiates");
509
    /// 507 Insufficient Storage
510
    /// [[RFC4918, Section 11.5](https://datatracker.ietf.org/doc/html/rfc4918#section-11.5)]
511
    (507, INSUFFICIENT_STORAGE, "Insufficient Storage");
512
    /// 508 Loop Detected
513
    /// [[RFC5842, Section 7.2](https://datatracker.ietf.org/doc/html/rfc5842#section-7.2)]
514
    (508, LOOP_DETECTED, "Loop Detected");
515
516
    /// 510 Not Extended
517
    /// [[RFC2774, Section 7](https://datatracker.ietf.org/doc/html/rfc2774#section-7)]
518
    (510, NOT_EXTENDED, "Not Extended");
519
    /// 511 Network Authentication Required
520
    /// [[RFC6585, Section 6](https://datatracker.ietf.org/doc/html/rfc6585#section-6)]
521
    (511, NETWORK_AUTHENTICATION_REQUIRED, "Network Authentication Required");
522
}
523
524
impl InvalidStatusCode {
525
5.79k
    const fn new() -> InvalidStatusCode {
526
5.79k
        InvalidStatusCode { _priv: () }
527
5.79k
    }
528
}
529
530
impl fmt::Debug for InvalidStatusCode {
531
0
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
532
0
        f.debug_struct("InvalidStatusCode")
533
            // skip _priv noise
534
0
            .finish()
535
0
    }
536
}
537
538
impl fmt::Display for InvalidStatusCode {
539
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
540
0
        f.write_str("invalid status code")
541
0
    }
542
}
543
544
impl Error for InvalidStatusCode {}
545
546
// A string of packed 3-ASCII-digit status code values for the supported range
547
// of [100, 999] (900 codes, 2700 bytes).
548
const CODE_DIGITS: &str = "\
549
100101102103104105106107108109110111112113114115116117118119\
550
120121122123124125126127128129130131132133134135136137138139\
551
140141142143144145146147148149150151152153154155156157158159\
552
160161162163164165166167168169170171172173174175176177178179\
553
180181182183184185186187188189190191192193194195196197198199\
554
200201202203204205206207208209210211212213214215216217218219\
555
220221222223224225226227228229230231232233234235236237238239\
556
240241242243244245246247248249250251252253254255256257258259\
557
260261262263264265266267268269270271272273274275276277278279\
558
280281282283284285286287288289290291292293294295296297298299\
559
300301302303304305306307308309310311312313314315316317318319\
560
320321322323324325326327328329330331332333334335336337338339\
561
340341342343344345346347348349350351352353354355356357358359\
562
360361362363364365366367368369370371372373374375376377378379\
563
380381382383384385386387388389390391392393394395396397398399\
564
400401402403404405406407408409410411412413414415416417418419\
565
420421422423424425426427428429430431432433434435436437438439\
566
440441442443444445446447448449450451452453454455456457458459\
567
460461462463464465466467468469470471472473474475476477478479\
568
480481482483484485486487488489490491492493494495496497498499\
569
500501502503504505506507508509510511512513514515516517518519\
570
520521522523524525526527528529530531532533534535536537538539\
571
540541542543544545546547548549550551552553554555556557558559\
572
560561562563564565566567568569570571572573574575576577578579\
573
580581582583584585586587588589590591592593594595596597598599\
574
600601602603604605606607608609610611612613614615616617618619\
575
620621622623624625626627628629630631632633634635636637638639\
576
640641642643644645646647648649650651652653654655656657658659\
577
660661662663664665666667668669670671672673674675676677678679\
578
680681682683684685686687688689690691692693694695696697698699\
579
700701702703704705706707708709710711712713714715716717718719\
580
720721722723724725726727728729730731732733734735736737738739\
581
740741742743744745746747748749750751752753754755756757758759\
582
760761762763764765766767768769770771772773774775776777778779\
583
780781782783784785786787788789790791792793794795796797798799\
584
800801802803804805806807808809810811812813814815816817818819\
585
820821822823824825826827828829830831832833834835836837838839\
586
840841842843844845846847848849850851852853854855856857858859\
587
860861862863864865866867868869870871872873874875876877878879\
588
880881882883884885886887888889890891892893894895896897898899\
589
900901902903904905906907908909910911912913914915916917918919\
590
920921922923924925926927928929930931932933934935936937938939\
591
940941942943944945946947948949950951952953954955956957958959\
592
960961962963964965966967968969970971972973974975976977978979\
593
980981982983984985986987988989990991992993994995996997998999";