589 lines
21 KiB
Rust
589 lines
21 KiB
Rust
//! HTTP status codes
|
||
//!
|
||
//! This module contains HTTP-status code related structs an errors. The main
|
||
//! type in this module is `StatusCode` which is not intended to be used through
|
||
//! this module but rather the `http::StatusCode` type.
|
||
//!
|
||
//! # Examples
|
||
//!
|
||
//! ```
|
||
//! use http::StatusCode;
|
||
//!
|
||
//! assert_eq!(StatusCode::from_u16(200).unwrap(), StatusCode::OK);
|
||
//! assert_eq!(StatusCode::NOT_FOUND, 404);
|
||
//! assert!(StatusCode::OK.is_success());
|
||
//! ```
|
||
|
||
use std::convert::TryFrom;
|
||
use std::num::NonZeroU16;
|
||
use std::error::Error;
|
||
use std::fmt;
|
||
use std::str::FromStr;
|
||
|
||
/// An HTTP status code (`status-code` in RFC 7230 et al.).
|
||
///
|
||
/// Constants are provided for known status codes, including those in the IANA
|
||
/// [HTTP Status Code Registry](
|
||
/// https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml).
|
||
///
|
||
/// Status code values in the range 100-999 (inclusive) are supported by this
|
||
/// type. Values in the range 100-599 are semantically classified by the most
|
||
/// significant digit. See [`StatusCode::is_success`], etc. Values above 599
|
||
/// are unclassified but allowed for legacy compatibility, though their use is
|
||
/// discouraged. Applications may interpret such values as protocol errors.
|
||
///
|
||
/// # Examples
|
||
///
|
||
/// ```
|
||
/// use http::StatusCode;
|
||
///
|
||
/// assert_eq!(StatusCode::from_u16(200).unwrap(), StatusCode::OK);
|
||
/// assert_eq!(StatusCode::NOT_FOUND.as_u16(), 404);
|
||
/// assert!(StatusCode::OK.is_success());
|
||
/// ```
|
||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||
pub struct StatusCode(NonZeroU16);
|
||
|
||
/// A possible error value when converting a `StatusCode` from a `u16` or `&str`
|
||
///
|
||
/// This error indicates that the supplied input was not a valid number, was less
|
||
/// than 100, or was greater than 999.
|
||
pub struct InvalidStatusCode {
|
||
_priv: (),
|
||
}
|
||
|
||
impl StatusCode {
|
||
/// Converts a u16 to a status code.
|
||
///
|
||
/// The function validates the correctness of the supplied u16. It must be
|
||
/// greater or equal to 100 and less than 1000.
|
||
///
|
||
/// # Example
|
||
///
|
||
/// ```
|
||
/// use http::StatusCode;
|
||
///
|
||
/// let ok = StatusCode::from_u16(200).unwrap();
|
||
/// assert_eq!(ok, StatusCode::OK);
|
||
///
|
||
/// let err = StatusCode::from_u16(99);
|
||
/// assert!(err.is_err());
|
||
/// ```
|
||
#[inline]
|
||
pub fn from_u16(src: u16) -> Result<StatusCode, InvalidStatusCode> {
|
||
if src < 100 || src >= 1000 {
|
||
return Err(InvalidStatusCode::new());
|
||
}
|
||
|
||
NonZeroU16::new(src)
|
||
.map(StatusCode)
|
||
.ok_or_else(InvalidStatusCode::new)
|
||
}
|
||
|
||
/// Converts a &[u8] to a status code
|
||
pub fn from_bytes(src: &[u8]) -> Result<StatusCode, InvalidStatusCode> {
|
||
if src.len() != 3 {
|
||
return Err(InvalidStatusCode::new());
|
||
}
|
||
|
||
let a = src[0].wrapping_sub(b'0') as u16;
|
||
let b = src[1].wrapping_sub(b'0') as u16;
|
||
let c = src[2].wrapping_sub(b'0') as u16;
|
||
|
||
if a == 0 || a > 9 || b > 9 || c > 9 {
|
||
return Err(InvalidStatusCode::new());
|
||
}
|
||
|
||
let status = (a * 100) + (b * 10) + c;
|
||
NonZeroU16::new(status)
|
||
.map(StatusCode)
|
||
.ok_or_else(InvalidStatusCode::new)
|
||
}
|
||
|
||
/// Returns the `u16` corresponding to this `StatusCode`.
|
||
///
|
||
/// # Note
|
||
///
|
||
/// This is the same as the `From<StatusCode>` implementation, but
|
||
/// included as an inherent method because that implementation doesn't
|
||
/// appear in rustdocs, as well as a way to force the type instead of
|
||
/// relying on inference.
|
||
///
|
||
/// # Example
|
||
///
|
||
/// ```
|
||
/// let status = http::StatusCode::OK;
|
||
/// assert_eq!(status.as_u16(), 200);
|
||
/// ```
|
||
#[inline]
|
||
pub fn as_u16(&self) -> u16 {
|
||
(*self).into()
|
||
}
|
||
|
||
/// Returns a &str representation of the `StatusCode`
|
||
///
|
||
/// The return value only includes a numerical representation of the
|
||
/// status code. The canonical reason is not included.
|
||
///
|
||
/// # Example
|
||
///
|
||
/// ```
|
||
/// let status = http::StatusCode::OK;
|
||
/// assert_eq!(status.as_str(), "200");
|
||
/// ```
|
||
#[inline]
|
||
pub fn as_str(&self) -> &str {
|
||
let offset = (self.0.get() - 100) as usize;
|
||
let offset = offset * 3;
|
||
|
||
// Invariant: self has checked range [100, 999] and CODE_DIGITS is
|
||
// ASCII-only, of length 900 * 3 = 2700 bytes
|
||
|
||
#[cfg(debug_assertions)]
|
||
{ &CODE_DIGITS[offset..offset+3] }
|
||
|
||
#[cfg(not(debug_assertions))]
|
||
unsafe { CODE_DIGITS.get_unchecked(offset..offset+3) }
|
||
}
|
||
|
||
/// Get the standardised `reason-phrase` for this status code.
|
||
///
|
||
/// This is mostly here for servers writing responses, but could potentially have application
|
||
/// at other times.
|
||
///
|
||
/// The reason phrase is defined as being exclusively for human readers. You should avoid
|
||
/// deriving any meaning from it at all costs.
|
||
///
|
||
/// Bear in mind also that in HTTP/2.0 and HTTP/3.0 the reason phrase is abolished from
|
||
/// transmission, and so this canonical reason phrase really is the only reason phrase you’ll
|
||
/// find.
|
||
///
|
||
/// # Example
|
||
///
|
||
/// ```
|
||
/// let status = http::StatusCode::OK;
|
||
/// assert_eq!(status.canonical_reason(), Some("OK"));
|
||
/// ```
|
||
pub fn canonical_reason(&self) -> Option<&'static str> {
|
||
canonical_reason(self.0.get())
|
||
}
|
||
|
||
/// Check if status is within 100-199.
|
||
#[inline]
|
||
pub fn is_informational(&self) -> bool {
|
||
200 > self.0.get() && self.0.get() >= 100
|
||
}
|
||
|
||
/// Check if status is within 200-299.
|
||
#[inline]
|
||
pub fn is_success(&self) -> bool {
|
||
300 > self.0.get() && self.0.get() >= 200
|
||
}
|
||
|
||
/// Check if status is within 300-399.
|
||
#[inline]
|
||
pub fn is_redirection(&self) -> bool {
|
||
400 > self.0.get() && self.0.get() >= 300
|
||
}
|
||
|
||
/// Check if status is within 400-499.
|
||
#[inline]
|
||
pub fn is_client_error(&self) -> bool {
|
||
500 > self.0.get() && self.0.get() >= 400
|
||
}
|
||
|
||
/// Check if status is within 500-599.
|
||
#[inline]
|
||
pub fn is_server_error(&self) -> bool {
|
||
600 > self.0.get() && self.0.get() >= 500
|
||
}
|
||
}
|
||
|
||
impl fmt::Debug for StatusCode {
|
||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||
fmt::Debug::fmt(&self.0, f)
|
||
}
|
||
}
|
||
|
||
/// Formats the status code, *including* the canonical reason.
|
||
///
|
||
/// # Example
|
||
///
|
||
/// ```
|
||
/// # use http::StatusCode;
|
||
/// assert_eq!(format!("{}", StatusCode::OK), "200 OK");
|
||
/// ```
|
||
impl fmt::Display for StatusCode {
|
||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||
write!(
|
||
f,
|
||
"{} {}",
|
||
u16::from(*self),
|
||
self.canonical_reason().unwrap_or("<unknown status code>")
|
||
)
|
||
}
|
||
}
|
||
|
||
impl Default for StatusCode {
|
||
#[inline]
|
||
fn default() -> StatusCode {
|
||
StatusCode::OK
|
||
}
|
||
}
|
||
|
||
impl PartialEq<u16> for StatusCode {
|
||
#[inline]
|
||
fn eq(&self, other: &u16) -> bool {
|
||
self.as_u16() == *other
|
||
}
|
||
}
|
||
|
||
impl PartialEq<StatusCode> for u16 {
|
||
#[inline]
|
||
fn eq(&self, other: &StatusCode) -> bool {
|
||
*self == other.as_u16()
|
||
}
|
||
}
|
||
|
||
impl From<StatusCode> for u16 {
|
||
#[inline]
|
||
fn from(status: StatusCode) -> u16 {
|
||
status.0.get()
|
||
}
|
||
}
|
||
|
||
impl FromStr for StatusCode {
|
||
type Err = InvalidStatusCode;
|
||
|
||
fn from_str(s: &str) -> Result<StatusCode, InvalidStatusCode> {
|
||
StatusCode::from_bytes(s.as_ref())
|
||
}
|
||
}
|
||
|
||
impl<'a> From<&'a StatusCode> for StatusCode {
|
||
#[inline]
|
||
fn from(t: &'a StatusCode) -> Self {
|
||
t.clone()
|
||
}
|
||
}
|
||
|
||
impl<'a> TryFrom<&'a [u8]> for StatusCode {
|
||
type Error = InvalidStatusCode;
|
||
|
||
#[inline]
|
||
fn try_from(t: &'a [u8]) -> Result<Self, Self::Error> {
|
||
StatusCode::from_bytes(t)
|
||
}
|
||
}
|
||
|
||
impl<'a> TryFrom<&'a str> for StatusCode {
|
||
type Error = InvalidStatusCode;
|
||
|
||
#[inline]
|
||
fn try_from(t: &'a str) -> Result<Self, Self::Error> {
|
||
t.parse()
|
||
}
|
||
}
|
||
|
||
impl TryFrom<u16> for StatusCode {
|
||
type Error = InvalidStatusCode;
|
||
|
||
#[inline]
|
||
fn try_from(t: u16) -> Result<Self, Self::Error> {
|
||
StatusCode::from_u16(t)
|
||
}
|
||
}
|
||
|
||
macro_rules! status_codes {
|
||
(
|
||
$(
|
||
$(#[$docs:meta])*
|
||
($num:expr, $konst:ident, $phrase:expr);
|
||
)+
|
||
) => {
|
||
impl StatusCode {
|
||
$(
|
||
$(#[$docs])*
|
||
pub const $konst: StatusCode = StatusCode(unsafe { NonZeroU16::new_unchecked($num) });
|
||
)+
|
||
|
||
}
|
||
|
||
fn canonical_reason(num: u16) -> Option<&'static str> {
|
||
match num {
|
||
$(
|
||
$num => Some($phrase),
|
||
)+
|
||
_ => None
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
status_codes! {
|
||
/// 100 Continue
|
||
/// [[RFC7231, Section 6.2.1](https://tools.ietf.org/html/rfc7231#section-6.2.1)]
|
||
(100, CONTINUE, "Continue");
|
||
/// 101 Switching Protocols
|
||
/// [[RFC7231, Section 6.2.2](https://tools.ietf.org/html/rfc7231#section-6.2.2)]
|
||
(101, SWITCHING_PROTOCOLS, "Switching Protocols");
|
||
/// 102 Processing
|
||
/// [[RFC2518](https://tools.ietf.org/html/rfc2518)]
|
||
(102, PROCESSING, "Processing");
|
||
|
||
/// 200 OK
|
||
/// [[RFC7231, Section 6.3.1](https://tools.ietf.org/html/rfc7231#section-6.3.1)]
|
||
(200, OK, "OK");
|
||
/// 201 Created
|
||
/// [[RFC7231, Section 6.3.2](https://tools.ietf.org/html/rfc7231#section-6.3.2)]
|
||
(201, CREATED, "Created");
|
||
/// 202 Accepted
|
||
/// [[RFC7231, Section 6.3.3](https://tools.ietf.org/html/rfc7231#section-6.3.3)]
|
||
(202, ACCEPTED, "Accepted");
|
||
/// 203 Non-Authoritative Information
|
||
/// [[RFC7231, Section 6.3.4](https://tools.ietf.org/html/rfc7231#section-6.3.4)]
|
||
(203, NON_AUTHORITATIVE_INFORMATION, "Non Authoritative Information");
|
||
/// 204 No Content
|
||
/// [[RFC7231, Section 6.3.5](https://tools.ietf.org/html/rfc7231#section-6.3.5)]
|
||
(204, NO_CONTENT, "No Content");
|
||
/// 205 Reset Content
|
||
/// [[RFC7231, Section 6.3.6](https://tools.ietf.org/html/rfc7231#section-6.3.6)]
|
||
(205, RESET_CONTENT, "Reset Content");
|
||
/// 206 Partial Content
|
||
/// [[RFC7233, Section 4.1](https://tools.ietf.org/html/rfc7233#section-4.1)]
|
||
(206, PARTIAL_CONTENT, "Partial Content");
|
||
/// 207 Multi-Status
|
||
/// [[RFC4918](https://tools.ietf.org/html/rfc4918)]
|
||
(207, MULTI_STATUS, "Multi-Status");
|
||
/// 208 Already Reported
|
||
/// [[RFC5842](https://tools.ietf.org/html/rfc5842)]
|
||
(208, ALREADY_REPORTED, "Already Reported");
|
||
|
||
/// 226 IM Used
|
||
/// [[RFC3229](https://tools.ietf.org/html/rfc3229)]
|
||
(226, IM_USED, "IM Used");
|
||
|
||
/// 300 Multiple Choices
|
||
/// [[RFC7231, Section 6.4.1](https://tools.ietf.org/html/rfc7231#section-6.4.1)]
|
||
(300, MULTIPLE_CHOICES, "Multiple Choices");
|
||
/// 301 Moved Permanently
|
||
/// [[RFC7231, Section 6.4.2](https://tools.ietf.org/html/rfc7231#section-6.4.2)]
|
||
(301, MOVED_PERMANENTLY, "Moved Permanently");
|
||
/// 302 Found
|
||
/// [[RFC7231, Section 6.4.3](https://tools.ietf.org/html/rfc7231#section-6.4.3)]
|
||
(302, FOUND, "Found");
|
||
/// 303 See Other
|
||
/// [[RFC7231, Section 6.4.4](https://tools.ietf.org/html/rfc7231#section-6.4.4)]
|
||
(303, SEE_OTHER, "See Other");
|
||
/// 304 Not Modified
|
||
/// [[RFC7232, Section 4.1](https://tools.ietf.org/html/rfc7232#section-4.1)]
|
||
(304, NOT_MODIFIED, "Not Modified");
|
||
/// 305 Use Proxy
|
||
/// [[RFC7231, Section 6.4.5](https://tools.ietf.org/html/rfc7231#section-6.4.5)]
|
||
(305, USE_PROXY, "Use Proxy");
|
||
/// 307 Temporary Redirect
|
||
/// [[RFC7231, Section 6.4.7](https://tools.ietf.org/html/rfc7231#section-6.4.7)]
|
||
(307, TEMPORARY_REDIRECT, "Temporary Redirect");
|
||
/// 308 Permanent Redirect
|
||
/// [[RFC7238](https://tools.ietf.org/html/rfc7238)]
|
||
(308, PERMANENT_REDIRECT, "Permanent Redirect");
|
||
|
||
/// 400 Bad Request
|
||
/// [[RFC7231, Section 6.5.1](https://tools.ietf.org/html/rfc7231#section-6.5.1)]
|
||
(400, BAD_REQUEST, "Bad Request");
|
||
/// 401 Unauthorized
|
||
/// [[RFC7235, Section 3.1](https://tools.ietf.org/html/rfc7235#section-3.1)]
|
||
(401, UNAUTHORIZED, "Unauthorized");
|
||
/// 402 Payment Required
|
||
/// [[RFC7231, Section 6.5.2](https://tools.ietf.org/html/rfc7231#section-6.5.2)]
|
||
(402, PAYMENT_REQUIRED, "Payment Required");
|
||
/// 403 Forbidden
|
||
/// [[RFC7231, Section 6.5.3](https://tools.ietf.org/html/rfc7231#section-6.5.3)]
|
||
(403, FORBIDDEN, "Forbidden");
|
||
/// 404 Not Found
|
||
/// [[RFC7231, Section 6.5.4](https://tools.ietf.org/html/rfc7231#section-6.5.4)]
|
||
(404, NOT_FOUND, "Not Found");
|
||
/// 405 Method Not Allowed
|
||
/// [[RFC7231, Section 6.5.5](https://tools.ietf.org/html/rfc7231#section-6.5.5)]
|
||
(405, METHOD_NOT_ALLOWED, "Method Not Allowed");
|
||
/// 406 Not Acceptable
|
||
/// [[RFC7231, Section 6.5.6](https://tools.ietf.org/html/rfc7231#section-6.5.6)]
|
||
(406, NOT_ACCEPTABLE, "Not Acceptable");
|
||
/// 407 Proxy Authentication Required
|
||
/// [[RFC7235, Section 3.2](https://tools.ietf.org/html/rfc7235#section-3.2)]
|
||
(407, PROXY_AUTHENTICATION_REQUIRED, "Proxy Authentication Required");
|
||
/// 408 Request Timeout
|
||
/// [[RFC7231, Section 6.5.7](https://tools.ietf.org/html/rfc7231#section-6.5.7)]
|
||
(408, REQUEST_TIMEOUT, "Request Timeout");
|
||
/// 409 Conflict
|
||
/// [[RFC7231, Section 6.5.8](https://tools.ietf.org/html/rfc7231#section-6.5.8)]
|
||
(409, CONFLICT, "Conflict");
|
||
/// 410 Gone
|
||
/// [[RFC7231, Section 6.5.9](https://tools.ietf.org/html/rfc7231#section-6.5.9)]
|
||
(410, GONE, "Gone");
|
||
/// 411 Length Required
|
||
/// [[RFC7231, Section 6.5.10](https://tools.ietf.org/html/rfc7231#section-6.5.10)]
|
||
(411, LENGTH_REQUIRED, "Length Required");
|
||
/// 412 Precondition Failed
|
||
/// [[RFC7232, Section 4.2](https://tools.ietf.org/html/rfc7232#section-4.2)]
|
||
(412, PRECONDITION_FAILED, "Precondition Failed");
|
||
/// 413 Payload Too Large
|
||
/// [[RFC7231, Section 6.5.11](https://tools.ietf.org/html/rfc7231#section-6.5.11)]
|
||
(413, PAYLOAD_TOO_LARGE, "Payload Too Large");
|
||
/// 414 URI Too Long
|
||
/// [[RFC7231, Section 6.5.12](https://tools.ietf.org/html/rfc7231#section-6.5.12)]
|
||
(414, URI_TOO_LONG, "URI Too Long");
|
||
/// 415 Unsupported Media Type
|
||
/// [[RFC7231, Section 6.5.13](https://tools.ietf.org/html/rfc7231#section-6.5.13)]
|
||
(415, UNSUPPORTED_MEDIA_TYPE, "Unsupported Media Type");
|
||
/// 416 Range Not Satisfiable
|
||
/// [[RFC7233, Section 4.4](https://tools.ietf.org/html/rfc7233#section-4.4)]
|
||
(416, RANGE_NOT_SATISFIABLE, "Range Not Satisfiable");
|
||
/// 417 Expectation Failed
|
||
/// [[RFC7231, Section 6.5.14](https://tools.ietf.org/html/rfc7231#section-6.5.14)]
|
||
(417, EXPECTATION_FAILED, "Expectation Failed");
|
||
/// 418 I'm a teapot
|
||
/// [curiously not registered by IANA but [RFC2324](https://tools.ietf.org/html/rfc2324)]
|
||
(418, IM_A_TEAPOT, "I'm a teapot");
|
||
|
||
/// 421 Misdirected Request
|
||
/// [RFC7540, Section 9.1.2](http://tools.ietf.org/html/rfc7540#section-9.1.2)
|
||
(421, MISDIRECTED_REQUEST, "Misdirected Request");
|
||
/// 422 Unprocessable Entity
|
||
/// [[RFC4918](https://tools.ietf.org/html/rfc4918)]
|
||
(422, UNPROCESSABLE_ENTITY, "Unprocessable Entity");
|
||
/// 423 Locked
|
||
/// [[RFC4918](https://tools.ietf.org/html/rfc4918)]
|
||
(423, LOCKED, "Locked");
|
||
/// 424 Failed Dependency
|
||
/// [[RFC4918](https://tools.ietf.org/html/rfc4918)]
|
||
(424, FAILED_DEPENDENCY, "Failed Dependency");
|
||
|
||
/// 426 Upgrade Required
|
||
/// [[RFC7231, Section 6.5.15](https://tools.ietf.org/html/rfc7231#section-6.5.15)]
|
||
(426, UPGRADE_REQUIRED, "Upgrade Required");
|
||
|
||
/// 428 Precondition Required
|
||
/// [[RFC6585](https://tools.ietf.org/html/rfc6585)]
|
||
(428, PRECONDITION_REQUIRED, "Precondition Required");
|
||
/// 429 Too Many Requests
|
||
/// [[RFC6585](https://tools.ietf.org/html/rfc6585)]
|
||
(429, TOO_MANY_REQUESTS, "Too Many Requests");
|
||
|
||
/// 431 Request Header Fields Too Large
|
||
/// [[RFC6585](https://tools.ietf.org/html/rfc6585)]
|
||
(431, REQUEST_HEADER_FIELDS_TOO_LARGE, "Request Header Fields Too Large");
|
||
|
||
/// 451 Unavailable For Legal Reasons
|
||
/// [[RFC7725](http://tools.ietf.org/html/rfc7725)]
|
||
(451, UNAVAILABLE_FOR_LEGAL_REASONS, "Unavailable For Legal Reasons");
|
||
|
||
/// 500 Internal Server Error
|
||
/// [[RFC7231, Section 6.6.1](https://tools.ietf.org/html/rfc7231#section-6.6.1)]
|
||
(500, INTERNAL_SERVER_ERROR, "Internal Server Error");
|
||
/// 501 Not Implemented
|
||
/// [[RFC7231, Section 6.6.2](https://tools.ietf.org/html/rfc7231#section-6.6.2)]
|
||
(501, NOT_IMPLEMENTED, "Not Implemented");
|
||
/// 502 Bad Gateway
|
||
/// [[RFC7231, Section 6.6.3](https://tools.ietf.org/html/rfc7231#section-6.6.3)]
|
||
(502, BAD_GATEWAY, "Bad Gateway");
|
||
/// 503 Service Unavailable
|
||
/// [[RFC7231, Section 6.6.4](https://tools.ietf.org/html/rfc7231#section-6.6.4)]
|
||
(503, SERVICE_UNAVAILABLE, "Service Unavailable");
|
||
/// 504 Gateway Timeout
|
||
/// [[RFC7231, Section 6.6.5](https://tools.ietf.org/html/rfc7231#section-6.6.5)]
|
||
(504, GATEWAY_TIMEOUT, "Gateway Timeout");
|
||
/// 505 HTTP Version Not Supported
|
||
/// [[RFC7231, Section 6.6.6](https://tools.ietf.org/html/rfc7231#section-6.6.6)]
|
||
(505, HTTP_VERSION_NOT_SUPPORTED, "HTTP Version Not Supported");
|
||
/// 506 Variant Also Negotiates
|
||
/// [[RFC2295](https://tools.ietf.org/html/rfc2295)]
|
||
(506, VARIANT_ALSO_NEGOTIATES, "Variant Also Negotiates");
|
||
/// 507 Insufficient Storage
|
||
/// [[RFC4918](https://tools.ietf.org/html/rfc4918)]
|
||
(507, INSUFFICIENT_STORAGE, "Insufficient Storage");
|
||
/// 508 Loop Detected
|
||
/// [[RFC5842](https://tools.ietf.org/html/rfc5842)]
|
||
(508, LOOP_DETECTED, "Loop Detected");
|
||
|
||
/// 510 Not Extended
|
||
/// [[RFC2774](https://tools.ietf.org/html/rfc2774)]
|
||
(510, NOT_EXTENDED, "Not Extended");
|
||
/// 511 Network Authentication Required
|
||
/// [[RFC6585](https://tools.ietf.org/html/rfc6585)]
|
||
(511, NETWORK_AUTHENTICATION_REQUIRED, "Network Authentication Required");
|
||
}
|
||
|
||
impl InvalidStatusCode {
|
||
fn new() -> InvalidStatusCode {
|
||
InvalidStatusCode {
|
||
_priv: (),
|
||
}
|
||
}
|
||
}
|
||
|
||
impl fmt::Debug for InvalidStatusCode {
|
||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||
f.debug_struct("InvalidStatusCode")
|
||
// skip _priv noise
|
||
.finish()
|
||
}
|
||
}
|
||
|
||
impl fmt::Display for InvalidStatusCode {
|
||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||
f.write_str("invalid status code")
|
||
}
|
||
}
|
||
|
||
impl Error for InvalidStatusCode {}
|
||
|
||
// A string of packed 3-ASCII-digit status code values for the supported range
|
||
// of [100, 999] (900 codes, 2700 bytes).
|
||
const CODE_DIGITS: &'static str = "\
|
||
100101102103104105106107108109110111112113114115116117118119\
|
||
120121122123124125126127128129130131132133134135136137138139\
|
||
140141142143144145146147148149150151152153154155156157158159\
|
||
160161162163164165166167168169170171172173174175176177178179\
|
||
180181182183184185186187188189190191192193194195196197198199\
|
||
200201202203204205206207208209210211212213214215216217218219\
|
||
220221222223224225226227228229230231232233234235236237238239\
|
||
240241242243244245246247248249250251252253254255256257258259\
|
||
260261262263264265266267268269270271272273274275276277278279\
|
||
280281282283284285286287288289290291292293294295296297298299\
|
||
300301302303304305306307308309310311312313314315316317318319\
|
||
320321322323324325326327328329330331332333334335336337338339\
|
||
340341342343344345346347348349350351352353354355356357358359\
|
||
360361362363364365366367368369370371372373374375376377378379\
|
||
380381382383384385386387388389390391392393394395396397398399\
|
||
400401402403404405406407408409410411412413414415416417418419\
|
||
420421422423424425426427428429430431432433434435436437438439\
|
||
440441442443444445446447448449450451452453454455456457458459\
|
||
460461462463464465466467468469470471472473474475476477478479\
|
||
480481482483484485486487488489490491492493494495496497498499\
|
||
500501502503504505506507508509510511512513514515516517518519\
|
||
520521522523524525526527528529530531532533534535536537538539\
|
||
540541542543544545546547548549550551552553554555556557558559\
|
||
560561562563564565566567568569570571572573574575576577578579\
|
||
580581582583584585586587588589590591592593594595596597598599\
|
||
600601602603604605606607608609610611612613614615616617618619\
|
||
620621622623624625626627628629630631632633634635636637638639\
|
||
640641642643644645646647648649650651652653654655656657658659\
|
||
660661662663664665666667668669670671672673674675676677678679\
|
||
680681682683684685686687688689690691692693694695696697698699\
|
||
700701702703704705706707708709710711712713714715716717718719\
|
||
720721722723724725726727728729730731732733734735736737738739\
|
||
740741742743744745746747748749750751752753754755756757758759\
|
||
760761762763764765766767768769770771772773774775776777778779\
|
||
780781782783784785786787788789790791792793794795796797798799\
|
||
800801802803804805806807808809810811812813814815816817818819\
|
||
820821822823824825826827828829830831832833834835836837838839\
|
||
840841842843844845846847848849850851852853854855856857858859\
|
||
860861862863864865866867868869870871872873874875876877878879\
|
||
880881882883884885886887888889890891892893894895896897898899\
|
||
900901902903904905906907908909910911912913914915916917918919\
|
||
920921922923924925926927928929930931932933934935936937938939\
|
||
940941942943944945946947948949950951952953954955956957958959\
|
||
960961962963964965966967968969970971972973974975976977978979\
|
||
980981982983984985986987988989990991992993994995996997998999";
|