1use std::error::Error;
8use std::fmt::{self, Display, Formatter};
9use std::str::FromStr;
10
11#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
13pub(crate) enum Version {
14 Http1_0,
15 #[default]
16 Http1_1,
17}
18
19impl FromStr for Version {
20 type Err = ();
21
22 fn from_str(s: &str) -> Result<Self, Self::Err> {
23 match s {
24 "HTTP/1.0" => Ok(Version::Http1_0),
25 _ => Ok(Version::Http1_1),
26 }
27 }
28}
29
30impl Display for Version {
31 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
32 write!(
33 f,
34 "{}",
35 match self {
36 Version::Http1_0 => "HTTP/1.0",
37 Version::Http1_1 => "HTTP/1.1",
38 }
39 )
40 }
41}
42
43#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
46pub enum Method {
47 #[default]
49 Get,
50 Head,
52 Post,
54 Put,
56 Delete,
58 Connect,
60 Options,
62 Trace,
64 Patch,
66}
67
68impl FromStr for Method {
69 type Err = InvalidMethodError;
70
71 fn from_str(s: &str) -> Result<Self, Self::Err> {
72 match s {
73 "GET" => Ok(Method::Get),
74 "HEAD" => Ok(Method::Head),
75 "POST" => Ok(Method::Post),
76 "PUT" => Ok(Method::Put),
77 "DELETE" => Ok(Method::Delete),
78 "CONNECT" => Ok(Method::Connect),
79 "OPTIONS" => Ok(Method::Options),
80 "TRACE" => Ok(Method::Trace),
81 "PATCH" => Ok(Method::Patch),
82 _ => Err(InvalidMethodError),
83 }
84 }
85}
86
87impl Display for Method {
88 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
89 write!(
90 f,
91 "{}",
92 match self {
93 Method::Get => "GET",
94 Method::Head => "HEAD",
95 Method::Post => "POST",
96 Method::Put => "PUT",
97 Method::Delete => "DELETE",
98 Method::Connect => "CONNECT",
99 Method::Options => "OPTIONS",
100 Method::Trace => "TRACE",
101 Method::Patch => "PATCH",
102 }
103 )
104 }
105}
106
107#[derive(Debug)]
109pub struct InvalidMethodError;
110
111impl Display for InvalidMethodError {
112 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
113 write!(f, "Invalid HTTP method")
114 }
115}
116
117impl Error for InvalidMethodError {}
118
119#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
122pub enum Status {
123 Continue = 100,
125 SwitchingProtocols = 101,
127 Processing = 102,
129 #[default]
131 Ok = 200,
132 Created = 201,
134 Accepted = 202,
136 NonAuthoritativeInformation = 203,
138 NoContent = 204,
140 ResetContent = 205,
142 PartialContent = 206,
144 MultiStatus = 207,
146 AlreadyReported = 208,
148 IMUsed = 226,
150 MultipleChoices = 300,
152 MovedPermanently = 301,
154 Found = 302,
156 SeeOther = 303,
158 NotModified = 304,
160 UseProxy = 305,
162 TemporaryRedirect = 307,
164 PermanentRedirect = 308,
166 BadRequest = 400,
168 Unauthorized = 401,
170 PaymentRequired = 402,
172 Forbidden = 403,
174 NotFound = 404,
176 MethodNotAllowed = 405,
178 NotAcceptable = 406,
180 ProxyAuthenticationRequired = 407,
182 RequestTimeout = 408,
184 Conflict = 409,
186 Gone = 410,
188 LengthRequired = 411,
190 PreconditionFailed = 412,
192 PayloadTooLarge = 413,
194 URITooLong = 414,
196 UnsupportedMediaType = 415,
198 RangeNotSatisfiable = 416,
200 ExpectationFailed = 417,
202 ImATeapot = 418,
204 MisdirectedRequest = 421,
206 UnprocessableEntity = 422,
208 Locked = 423,
210 FailedDependency = 424,
212 TooEarly = 425,
214 UpgradeRequired = 426,
216 PreconditionRequired = 428,
218 TooManyRequests = 429,
220 RequestHeaderFieldsTooLarge = 431,
222 UnavailableForLegalReasons = 451,
224 InternalServerError = 500,
226 NotImplemented = 501,
228 BadGateway = 502,
230 ServiceUnavailable = 503,
232 GatewayTimeout = 504,
234 HTTPVersionNotSupported = 505,
236 VariantAlsoNegotiates = 506,
238 InsufficientStorage = 507,
240 LoopDetected = 508,
242 NotExtended = 510,
244 NetworkAuthenticationRequired = 511,
246}
247
248impl TryFrom<i32> for Status {
249 type Error = InvalidStatusError;
250
251 fn try_from(value: i32) -> Result<Self, Self::Error> {
252 match value {
253 100 => Ok(Status::Continue),
254 101 => Ok(Status::SwitchingProtocols),
255 102 => Ok(Status::Processing),
256 200 => Ok(Status::Ok),
257 201 => Ok(Status::Created),
258 202 => Ok(Status::Accepted),
259 203 => Ok(Status::NonAuthoritativeInformation),
260 204 => Ok(Status::NoContent),
261 205 => Ok(Status::ResetContent),
262 206 => Ok(Status::PartialContent),
263 207 => Ok(Status::MultiStatus),
264 208 => Ok(Status::AlreadyReported),
265 226 => Ok(Status::IMUsed),
266 300 => Ok(Status::MultipleChoices),
267 301 => Ok(Status::MovedPermanently),
268 302 => Ok(Status::Found),
269 303 => Ok(Status::SeeOther),
270 304 => Ok(Status::NotModified),
271 305 => Ok(Status::UseProxy),
272 307 => Ok(Status::TemporaryRedirect),
273 308 => Ok(Status::PermanentRedirect),
274 400 => Ok(Status::BadRequest),
275 401 => Ok(Status::Unauthorized),
276 402 => Ok(Status::PaymentRequired),
277 403 => Ok(Status::Forbidden),
278 404 => Ok(Status::NotFound),
279 405 => Ok(Status::MethodNotAllowed),
280 406 => Ok(Status::NotAcceptable),
281 407 => Ok(Status::ProxyAuthenticationRequired),
282 408 => Ok(Status::RequestTimeout),
283 409 => Ok(Status::Conflict),
284 410 => Ok(Status::Gone),
285 411 => Ok(Status::LengthRequired),
286 412 => Ok(Status::PreconditionFailed),
287 413 => Ok(Status::PayloadTooLarge),
288 414 => Ok(Status::URITooLong),
289 415 => Ok(Status::UnsupportedMediaType),
290 416 => Ok(Status::RangeNotSatisfiable),
291 417 => Ok(Status::ExpectationFailed),
292 418 => Ok(Status::ImATeapot),
293 421 => Ok(Status::MisdirectedRequest),
294 422 => Ok(Status::UnprocessableEntity),
295 423 => Ok(Status::Locked),
296 424 => Ok(Status::FailedDependency),
297 425 => Ok(Status::TooEarly),
298 426 => Ok(Status::UpgradeRequired),
299 428 => Ok(Status::PreconditionRequired),
300 429 => Ok(Status::TooManyRequests),
301 431 => Ok(Status::RequestHeaderFieldsTooLarge),
302 451 => Ok(Status::UnavailableForLegalReasons),
303 500 => Ok(Status::InternalServerError),
304 501 => Ok(Status::NotImplemented),
305 502 => Ok(Status::BadGateway),
306 503 => Ok(Status::ServiceUnavailable),
307 504 => Ok(Status::GatewayTimeout),
308 505 => Ok(Status::HTTPVersionNotSupported),
309 506 => Ok(Status::VariantAlsoNegotiates),
310 507 => Ok(Status::InsufficientStorage),
311 508 => Ok(Status::LoopDetected),
312 510 => Ok(Status::NotExtended),
313 511 => Ok(Status::NetworkAuthenticationRequired),
314 _ => Err(InvalidStatusError),
315 }
316 }
317}
318
319impl Display for Status {
320 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
321 write!(
322 f,
323 "{}",
324 match self {
325 Status::Continue => "100 Continue",
326 Status::SwitchingProtocols => "101 Switching Protocols",
327 Status::Processing => "102 Processing",
328 Status::Ok => "200 OK",
329 Status::Created => "201 Created",
330 Status::Accepted => "202 Accepted",
331 Status::NonAuthoritativeInformation => "203 Non-Authoritative Information",
332 Status::NoContent => "204 No Content",
333 Status::ResetContent => "205 Reset Content",
334 Status::PartialContent => "206 Partial Content",
335 Status::MultiStatus => "207 Multi-Status",
336 Status::AlreadyReported => "208 Already Reported",
337 Status::IMUsed => "226 IM Used",
338 Status::MultipleChoices => "300 Multiple Choices",
339 Status::MovedPermanently => "301 Moved Permanently",
340 Status::Found => "302 Found",
341 Status::SeeOther => "303 See Other",
342 Status::NotModified => "304 Not Modified",
343 Status::UseProxy => "305 Use Proxy",
344 Status::TemporaryRedirect => "307 Temporary Redirect",
345 Status::PermanentRedirect => "308 Permanent Redirect",
346 Status::BadRequest => "400 Bad Request",
347 Status::Unauthorized => "401 Unauthorized",
348 Status::PaymentRequired => "402 Payment Required",
349 Status::Forbidden => "403 Forbidden",
350 Status::NotFound => "404 Not Found",
351 Status::MethodNotAllowed => "405 Method Not Allowed",
352 Status::NotAcceptable => "406 Not Acceptable",
353 Status::ProxyAuthenticationRequired => "407 Proxy Authentication Required",
354 Status::RequestTimeout => "408 Request Timeout",
355 Status::Conflict => "409 Conflict",
356 Status::Gone => "410 Gone",
357 Status::LengthRequired => "411 Length Required",
358 Status::PreconditionFailed => "412 Precondition Failed",
359 Status::PayloadTooLarge => "413 Payload Too Large",
360 Status::URITooLong => "414 URI Too Long",
361 Status::UnsupportedMediaType => "415 Unsupported Media Type",
362 Status::RangeNotSatisfiable => "416 Range Not Satisfiable",
363 Status::ExpectationFailed => "417 Expectation Failed",
364 Status::ImATeapot => "418 I'm a teapot",
365 Status::MisdirectedRequest => "421 Misdirected Request",
366 Status::UnprocessableEntity => "422 Unprocessable Entity",
367 Status::Locked => "423 Locked",
368 Status::FailedDependency => "424 Failed Dependency",
369 Status::TooEarly => "425 Too Early",
370 Status::UpgradeRequired => "426 Upgrade Required",
371 Status::PreconditionRequired => "428 Precondition Required",
372 Status::TooManyRequests => "429 Too Many Requests",
373 Status::RequestHeaderFieldsTooLarge => "431 Request Header Fields Too Large",
374 Status::UnavailableForLegalReasons => "451 Unavailable For Legal Reasons",
375 Status::InternalServerError => "500 Internal Server Error",
376 Status::NotImplemented => "501 Not Implemented",
377 Status::BadGateway => "502 Bad Gateway",
378 Status::ServiceUnavailable => "503 Service Unavailable",
379 Status::GatewayTimeout => "504 Gateway Timeout",
380 Status::HTTPVersionNotSupported => "505 HTTP Version Not Supported",
381 Status::VariantAlsoNegotiates => "506 Variant Also Negotiates",
382 Status::InsufficientStorage => "507 Insufficient Storage",
383 Status::LoopDetected => "508 Loop Detected",
384 Status::NotExtended => "510 Not Extended",
385 Status::NetworkAuthenticationRequired => "511 Network Authentication Required",
386 }
387 )
388 }
389}
390
391#[derive(Debug)]
393pub struct InvalidStatusError;
394
395impl Display for InvalidStatusError {
396 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
397 write!(f, "Invalid HTTP status")
398 }
399}
400
401impl Error for InvalidStatusError {}