1#![allow(missing_docs)]
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
4pub struct StatusCode(u16);
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
7pub enum StatusClass {
8 Informational,
9 Successful,
10 Redirection,
11 ClientError,
12 ServerError,
13}
14
15impl StatusCode {
16 #[must_use]
17 pub const fn new(code: u16) -> Option<Self> {
18 if code >= 100 && code <= 599 {
19 Some(Self(code))
20 } else {
21 None
22 }
23 }
24
25 #[must_use]
26 pub const fn as_u16(self) -> u16 {
27 self.0
28 }
29
30 #[must_use]
31 pub const fn class(self) -> StatusClass {
32 match self.0 {
33 100..=199 => StatusClass::Informational,
34 200..=299 => StatusClass::Successful,
35 300..=399 => StatusClass::Redirection,
36 400..=499 => StatusClass::ClientError,
37 _ => StatusClass::ServerError,
38 }
39 }
40
41 #[must_use]
42 pub const fn reason_phrase(self) -> &'static str {
43 match self.0 {
44 100 => "Continue",
45 101 => "Switching Protocols",
46 102 => "Processing",
47 103 => "Early Hints",
48 200 => "OK",
49 201 => "Created",
50 202 => "Accepted",
51 203 => "Non-Authoritative Information",
52 204 => "No Content",
53 205 => "Reset Content",
54 206 => "Partial Content",
55 207 => "Multi-Status",
56 208 => "Already Reported",
57 226 => "IM Used",
58 300 => "Multiple Choices",
59 301 => "Moved Permanently",
60 302 => "Found",
61 303 => "See Other",
62 304 => "Not Modified",
63 305 => "Use Proxy",
64 307 => "Temporary Redirect",
65 308 => "Permanent Redirect",
66 400 => "Bad Request",
67 401 => "Unauthorized",
68 402 => "Payment Required",
69 403 => "Forbidden",
70 404 => "Not Found",
71 405 => "Method Not Allowed",
72 406 => "Not Acceptable",
73 407 => "Proxy Authentication Required",
74 408 => "Request Timeout",
75 409 => "Conflict",
76 410 => "Gone",
77 411 => "Length Required",
78 412 => "Precondition Failed",
79 413 => "Content Too Large",
80 414 => "URI Too Long",
81 415 => "Unsupported Media Type",
82 416 => "Range Not Satisfiable",
83 417 => "Expectation Failed",
84 418 => "I'm a teapot",
85 421 => "Misdirected Request",
86 422 => "Unprocessable Content",
87 423 => "Locked",
88 424 => "Failed Dependency",
89 425 => "Too Early",
90 426 => "Upgrade Required",
91 428 => "Precondition Required",
92 429 => "Too Many Requests",
93 431 => "Request Header Fields Too Large",
94 451 => "Unavailable For Legal Reasons",
95 500 => "Internal Server Error",
96 501 => "Not Implemented",
97 502 => "Bad Gateway",
98 503 => "Service Unavailable",
99 504 => "Gateway Timeout",
100 505 => "HTTP Version Not Supported",
101 506 => "Variant Also Negotiates",
102 507 => "Insufficient Storage",
103 508 => "Loop Detected",
104 510 => "Not Extended",
105 511 => "Network Authentication Required",
106 _ => "Unknown Status Code",
107 }
108 }
109
110 #[must_use]
111 pub const fn is_cacheable_by_default(self) -> bool {
112 matches!(
113 self.0,
114 200 | 203 | 204 | 206 | 300 | 301 | 304 | 308 | 404 | 405 | 410 | 414 | 501
115 )
116 }
117
118 #[must_use]
119 pub const fn is_informational(self) -> bool {
120 matches!(self.class(), StatusClass::Informational)
121 }
122
123 #[must_use]
124 pub const fn is_successful(self) -> bool {
125 matches!(self.class(), StatusClass::Successful)
126 }
127
128 #[must_use]
129 pub const fn is_redirection(self) -> bool {
130 matches!(self.class(), StatusClass::Redirection)
131 }
132
133 #[must_use]
134 pub const fn is_client_error(self) -> bool {
135 matches!(self.class(), StatusClass::ClientError)
136 }
137
138 #[must_use]
139 pub const fn is_server_error(self) -> bool {
140 matches!(self.class(), StatusClass::ServerError)
141 }
142
143 #[must_use]
144 pub const fn is_interim(self) -> bool {
145 self.is_informational()
146 }
147
148 #[must_use]
149 pub const fn is_final(self) -> bool {
150 !self.is_interim()
151 }
152
153 #[must_use]
154 pub const fn is_redirection_method_preserving(self) -> bool {
155 matches!(self.0, 307 | 308)
156 }
157
158 #[must_use]
159 pub const fn is_redirection_suggests_get(self) -> bool {
160 matches!(self.0, 303)
161 }
162
163 pub const CONTINUE: Self = Self(100);
164 pub const SWITCHING_PROTOCOLS: Self = Self(101);
165 pub const PROCESSING: Self = Self(102);
166 pub const EARLY_HINTS: Self = Self(103);
167 pub const UPLOAD_RESUMPTION_SUPPORTED: Self = Self(104);
168
169 pub const OK: Self = Self(200);
170 pub const CREATED: Self = Self(201);
171 pub const ACCEPTED: Self = Self(202);
172 pub const NON_AUTHORITATIVE_INFORMATION: Self = Self(203);
173 pub const NO_CONTENT: Self = Self(204);
174 pub const RESET_CONTENT: Self = Self(205);
175 pub const PARTIAL_CONTENT: Self = Self(206);
176 pub const MULTI_STATUS: Self = Self(207);
177 pub const ALREADY_REPORTED: Self = Self(208);
178 pub const IM_USED: Self = Self(226);
179
180 pub const MULTIPLE_CHOICES: Self = Self(300);
181 pub const MOVED_PERMANENTLY: Self = Self(301);
182 pub const FOUND: Self = Self(302);
183 pub const SEE_OTHER: Self = Self(303);
184 pub const NOT_MODIFIED: Self = Self(304);
185 pub const USE_PROXY: Self = Self(305);
186 pub const UNUSED_306: Self = Self(306);
187 pub const TEMPORARY_REDIRECT: Self = Self(307);
188 pub const PERMANENT_REDIRECT: Self = Self(308);
189
190 pub const BAD_REQUEST: Self = Self(400);
191 pub const UNAUTHORIZED: Self = Self(401);
192 pub const PAYMENT_REQUIRED: Self = Self(402);
193 pub const FORBIDDEN: Self = Self(403);
194 pub const NOT_FOUND: Self = Self(404);
195 pub const METHOD_NOT_ALLOWED: Self = Self(405);
196 pub const NOT_ACCEPTABLE: Self = Self(406);
197 pub const PROXY_AUTHENTICATION_REQUIRED: Self = Self(407);
198 pub const REQUEST_TIMEOUT: Self = Self(408);
199 pub const CONFLICT: Self = Self(409);
200 pub const GONE: Self = Self(410);
201 pub const LENGTH_REQUIRED: Self = Self(411);
202 pub const PRECONDITION_FAILED: Self = Self(412);
203 pub const CONTENT_TOO_LARGE: Self = Self(413);
204 pub const URI_TOO_LONG: Self = Self(414);
205 pub const UNSUPPORTED_MEDIA_TYPE: Self = Self(415);
206 pub const RANGE_NOT_SATISFIABLE: Self = Self(416);
207 pub const EXPECTATION_FAILED: Self = Self(417);
208 pub const IM_A_TEAPOT: Self = Self(418);
209 pub const MISDIRECTED_REQUEST: Self = Self(421);
210 pub const UNPROCESSABLE_CONTENT: Self = Self(422);
211 pub const LOCKED: Self = Self(423);
212 pub const FAILED_DEPENDENCY: Self = Self(424);
213 pub const TOO_EARLY: Self = Self(425);
214 pub const UPGRADE_REQUIRED: Self = Self(426);
215 pub const PRECONDITION_REQUIRED: Self = Self(428);
216 pub const TOO_MANY_REQUESTS: Self = Self(429);
217 pub const REQUEST_HEADER_FIELDS_TOO_LARGE: Self = Self(431);
218 pub const UNAVAILABLE_FOR_LEGAL_REASONS: Self = Self(451);
219
220 pub const INTERNAL_SERVER_ERROR: Self = Self(500);
221 pub const NOT_IMPLEMENTED: Self = Self(501);
222 pub const BAD_GATEWAY: Self = Self(502);
223 pub const SERVICE_UNAVAILABLE: Self = Self(503);
224 pub const GATEWAY_TIMEOUT: Self = Self(504);
225 pub const HTTP_VERSION_NOT_SUPPORTED: Self = Self(505);
226 pub const VARIANT_ALSO_NEGOTIATES: Self = Self(506);
227 pub const INSUFFICIENT_STORAGE: Self = Self(507);
228 pub const LOOP_DETECTED: Self = Self(508);
229 pub const NOT_EXTENDED: Self = Self(510);
230 pub const NETWORK_AUTHENTICATION_REQUIRED: Self = Self(511);
231}