use core::{error, fmt};
use crate::core::Status;
use crate::ffi::*;
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct HTTPStatus(pub ngx_uint_t);
#[derive(Debug)]
pub struct InvalidHTTPStatusCode {
_priv: (),
}
impl InvalidHTTPStatusCode {
fn new() -> InvalidHTTPStatusCode {
InvalidHTTPStatusCode { _priv: () }
}
}
impl fmt::Display for InvalidHTTPStatusCode {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str("invalid status code")
}
}
impl error::Error for InvalidHTTPStatusCode {}
impl From<HTTPStatus> for Status {
fn from(val: HTTPStatus) -> Self {
Status(val.0 as ngx_int_t)
}
}
impl From<HTTPStatus> for ngx_uint_t {
fn from(val: HTTPStatus) -> Self {
val.0
}
}
impl fmt::Debug for HTTPStatus {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Debug::fmt(&self.0, f)
}
}
impl HTTPStatus {
#[inline]
pub fn from_u16(src: u16) -> Result<HTTPStatus, InvalidHTTPStatusCode> {
if !(100..600).contains(&src) {
return Err(InvalidHTTPStatusCode::new());
}
Ok(HTTPStatus(src.into()))
}
pub fn from_bytes(src: &[u8]) -> Result<HTTPStatus, InvalidHTTPStatusCode> {
if src.len() != 3 {
return Err(InvalidHTTPStatusCode::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 > 5 || b > 9 || c > 9 {
return Err(InvalidHTTPStatusCode::new());
}
let status = (a * 100) + (b * 10) + c;
Ok(HTTPStatus(status.into()))
}
}
macro_rules! http_status_codes {
(
$(
$(#[$docs:meta])*
($num:expr, $konst:ident, $phrase:expr);
)+
) => {
impl HTTPStatus {
$(
$(#[$docs])*
pub const $konst: HTTPStatus = HTTPStatus($num);
)+
}
}
}
http_status_codes! {
(100, CONTINUE, "Continue");
(101, SWITCHING_PROTOCOLS, "Switching Protocols");
(102, PROCESSING, "Processing");
(200, OK, "OK");
(201, CREATED, "Created");
(202, ACCEPTED, "Accepted");
(204, NO_CONTENT, "No Content");
(206, PARTIAL_CONTENT, "Partial Content");
(300, SPECIAL_RESPONSE, "SPECIAL_RESPONSE");
(301, MOVED_PERMANENTLY, "Moved Permanently");
(302, MOVED_TEMPORARILY, "Moved Temporarily");
(303, SEE_OTHER, "See Other");
(304, NOT_MODIFIED, "Not Modified");
(307, TEMPORARY_REDIRECT, "Temporary Redirect");
(308, PERMANENT_REDIRECT, "Permanent Redirect");
(400, BAD_REQUEST, "Bad Request");
(401, UNAUTHORIZED, "Unauthorized");
(403, FORBIDDEN, "Forbidden");
(404, NOT_FOUND, "Not Found");
(405, NOT_ALLOWED, "Method Not Allowed");
(408, REQUEST_TIME_OUT, "Request Time Out");
(409, CONFLICT, "Conflict");
(411, LENGTH_REQUIRED, "Length Required");
(412, PRECONDITION_FAILED, "Precondition Failed");
(413, REQUEST_ENTITY_TOO_LARGE, "Payload Too Large");
(414, REQUEST_URI_TOO_LARGE, "Request Uri Too Large");
(415, UNSUPPORTED_MEDIA_TYPE, "Unsupported Media Type");
(416, RANGE_NOT_SATISFIABLE, "Range Not Satisfiable");
(421, MISDIRECTED_REQUEST, "Misdirected Request");
(429, TOO_MANY_REQUESTS, "Too Many Requests");
(444, CLOSE, "CLOSE");
(494, NGINX_CODES, "NGINX_CODES");
(494, REQUEST_HEADER_TOO_LARGE, "REQUEST_HEADER_TOO_LARGE");
(495, HTTPS_CERT_ERROR, "NGX_HTTPS_CERT_ERROR");
(496, HTTPS_NO_CERT, "NGX_HTTPS_NO_CERT");
(497, TO_HTTPS, "TO_HTTPS");
(499, CLIENT_CLOSED_REQUEST, "CLIENT_CLOSED_REQUEST");
(500, INTERNAL_SERVER_ERROR, "INTERNAL_SERVER_ERROR");
(501, NOT_IMPLEMENTED, "NOT_IMPLEMENTED");
(502, BAD_GATEWAY, "BAD_GATEWAY");
(503, SERVICE_UNAVAILABLE, "SERVICE_UNAVAILABLE");
(504, GATEWAY_TIME_OUT, "GATEWAY_TIME_OUT");
(505, VERSION_NOT_SUPPORTED, "VERSION_NOT_SUPPORTED");
(507, INSUFFICIENT_STORAGE, "INSUFFICIENT_STORAGE");
}