1#![forbid(unsafe_code)]
2#![doc = include_str!("../README.md")]
3
4#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
6pub struct HttpStatus {
7 pub code: u16,
8 pub reason: &'static str,
9}
10
11#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
13pub enum StatusClass {
14 Informational,
15 Success,
16 Redirection,
17 ClientError,
18 ServerError,
19}
20
21#[must_use]
23pub const fn reason_phrase(code: u16) -> Option<&'static str> {
24 match code {
25 100 => Some("Continue"),
26 101 => Some("Switching Protocols"),
27 102 => Some("Processing"),
28 103 => Some("Early Hints"),
29 200 => Some("OK"),
30 201 => Some("Created"),
31 202 => Some("Accepted"),
32 204 => Some("No Content"),
33 206 => Some("Partial Content"),
34 300 => Some("Multiple Choices"),
35 301 => Some("Moved Permanently"),
36 302 => Some("Found"),
37 303 => Some("See Other"),
38 304 => Some("Not Modified"),
39 307 => Some("Temporary Redirect"),
40 308 => Some("Permanent Redirect"),
41 400 => Some("Bad Request"),
42 401 => Some("Unauthorized"),
43 403 => Some("Forbidden"),
44 404 => Some("Not Found"),
45 405 => Some("Method Not Allowed"),
46 409 => Some("Conflict"),
47 410 => Some("Gone"),
48 415 => Some("Unsupported Media Type"),
49 422 => Some("Unprocessable Content"),
50 429 => Some("Too Many Requests"),
51 500 => Some("Internal Server Error"),
52 501 => Some("Not Implemented"),
53 502 => Some("Bad Gateway"),
54 503 => Some("Service Unavailable"),
55 504 => Some("Gateway Timeout"),
56 _ => None,
57 }
58}
59
60#[must_use]
62pub const fn status_class(code: u16) -> Option<StatusClass> {
63 match code {
64 100..=199 => Some(StatusClass::Informational),
65 200..=299 => Some(StatusClass::Success),
66 300..=399 => Some(StatusClass::Redirection),
67 400..=499 => Some(StatusClass::ClientError),
68 500..=599 => Some(StatusClass::ServerError),
69 _ => None,
70 }
71}
72
73#[must_use]
75pub const fn is_informational(code: u16) -> bool {
76 matches!(status_class(code), Some(StatusClass::Informational))
77}
78
79#[must_use]
81pub const fn is_success(code: u16) -> bool {
82 matches!(status_class(code), Some(StatusClass::Success))
83}
84
85#[must_use]
87pub const fn is_redirect(code: u16) -> bool {
88 matches!(status_class(code), Some(StatusClass::Redirection))
89}
90
91#[must_use]
93pub const fn is_client_error(code: u16) -> bool {
94 matches!(status_class(code), Some(StatusClass::ClientError))
95}
96
97#[must_use]
99pub const fn is_server_error(code: u16) -> bool {
100 matches!(status_class(code), Some(StatusClass::ServerError))
101}
102
103#[must_use]
105pub const fn is_error(code: u16) -> bool {
106 is_client_error(code) || is_server_error(code)
107}
108
109#[must_use]
111pub const fn is_cacheable_by_default(code: u16) -> bool {
112 matches!(
113 code,
114 200 | 203 | 204 | 206 | 300 | 301 | 404 | 405 | 410 | 414 | 501
115 )
116}