http_type/http_status/
impl.rs

1use crate::*;
2
3/// The `HttpStatus` enum represents the HTTP status codes.
4///
5/// It maps common HTTP status codes to their respective meanings. It provides methods to retrieve
6/// the corresponding numeric code as well as the associated status text. Additionally, it implements
7/// conversion from a string representation of the status code.
8impl HttpStatus {
9    /// Gets the numeric HTTP status code.
10    ///
11    /// Returns the corresponding HTTP status code number for the enum variant.
12    ///
13    /// # Arguments
14    ///
15    /// - `&self` - The HttpStatus instance.
16    ///
17    /// # Returns
18    ///
19    /// - `u16` - The numeric status code.
20    pub fn code(&self) -> ResponseStatusCode {
21        match self {
22            Self::Continue => 100,
23            Self::SwitchingProtocols => 101,
24            Self::Processing => 102,
25            Self::EarlyHints => 103,
26            Self::Ok => 200,
27            Self::Created => 201,
28            Self::Accepted => 202,
29            Self::NonAuthoritativeInformation => 203,
30            Self::NoContent => 204,
31            Self::ResetContent => 205,
32            Self::PartialContent => 206,
33            Self::MultiStatus => 207,
34            Self::AlreadyReported => 208,
35            Self::IMUsed => 226,
36            Self::MultipleChoices => 300,
37            Self::MovedPermanently => 301,
38            Self::Found => 302,
39            Self::SeeOther => 303,
40            Self::NotModified => 304,
41            Self::UseProxy => 305,
42            Self::TemporaryRedirect => 307,
43            Self::PermanentRedirect => 308,
44            Self::BadRequest => 400,
45            Self::Unauthorized => 401,
46            Self::PaymentRequired => 402,
47            Self::Forbidden => 403,
48            Self::NotFound => 404,
49            Self::MethodNotAllowed => 405,
50            Self::NotAcceptable => 406,
51            Self::ProxyAuthenticationRequired => 407,
52            Self::RequestTimeout => 408,
53            Self::Conflict => 409,
54            Self::Gone => 410,
55            Self::LengthRequired => 411,
56            Self::PreconditionFailed => 412,
57            Self::PayloadTooLarge => 413,
58            Self::URITooLong => 414,
59            Self::UnsupportedMediaType => 415,
60            Self::RangeNotSatisfiable => 416,
61            Self::ExpectationFailed => 417,
62            Self::ImATeapot => 418,
63            Self::MisdirectedRequest => 421,
64            Self::UnprocessableEntity => 422,
65            Self::Locked => 423,
66            Self::FailedDependency => 424,
67            Self::TooEarly => 425,
68            Self::UpgradeRequired => 426,
69            Self::PreconditionRequired => 428,
70            Self::TooManyRequests => 429,
71            Self::RequestHeaderFieldsTooLarge => 431,
72            Self::UnavailableForLegalReasons => 451,
73            Self::InternalServerError => 500,
74            Self::NotImplemented => 501,
75            Self::BadGateway => 502,
76            Self::ServiceUnavailable => 503,
77            Self::GatewayTimeout => 504,
78            Self::HTTPVersionNotSupported => 505,
79            Self::VariantAlsoNegotiates => 506,
80            Self::InsufficientStorage => 507,
81            Self::LoopDetected => 508,
82            Self::NotExtended => 510,
83            Self::NetworkAuthenticationRequired => 511,
84            Self::Unknown => 0,
85        }
86    }
87
88    /// Gets the textual description for a status code.
89    ///
90    /// Returns the standard HTTP status text for the given numeric code.
91    ///
92    /// # Arguments
93    ///
94    /// - `u16` - The numeric HTTP status code.
95    ///
96    /// # Returns
97    ///
98    /// - `String` - The standard status text description.
99    pub fn phrase(code: ResponseStatusCode) -> String {
100        match code {
101            100 => Self::Continue.to_string(),
102            101 => Self::SwitchingProtocols.to_string(),
103            102 => Self::Processing.to_string(),
104            103 => Self::EarlyHints.to_string(),
105            200 => Self::Ok.to_string(),
106            201 => Self::Created.to_string(),
107            202 => Self::Accepted.to_string(),
108            203 => Self::NonAuthoritativeInformation.to_string(),
109            204 => Self::NoContent.to_string(),
110            205 => Self::ResetContent.to_string(),
111            206 => Self::PartialContent.to_string(),
112            207 => Self::MultiStatus.to_string(),
113            208 => Self::AlreadyReported.to_string(),
114            226 => Self::IMUsed.to_string(),
115            300 => Self::MultipleChoices.to_string(),
116            301 => Self::MovedPermanently.to_string(),
117            302 => Self::Found.to_string(),
118            303 => Self::SeeOther.to_string(),
119            304 => Self::NotModified.to_string(),
120            305 => Self::UseProxy.to_string(),
121            307 => Self::TemporaryRedirect.to_string(),
122            308 => Self::PermanentRedirect.to_string(),
123            400 => Self::BadRequest.to_string(),
124            401 => Self::Unauthorized.to_string(),
125            402 => Self::PaymentRequired.to_string(),
126            403 => Self::Forbidden.to_string(),
127            404 => Self::NotFound.to_string(),
128            405 => Self::MethodNotAllowed.to_string(),
129            406 => Self::NotAcceptable.to_string(),
130            407 => Self::ProxyAuthenticationRequired.to_string(),
131            408 => Self::RequestTimeout.to_string(),
132            409 => Self::Conflict.to_string(),
133            410 => Self::Gone.to_string(),
134            411 => Self::LengthRequired.to_string(),
135            412 => Self::PreconditionFailed.to_string(),
136            413 => Self::PayloadTooLarge.to_string(),
137            414 => Self::URITooLong.to_string(),
138            415 => Self::UnsupportedMediaType.to_string(),
139            416 => Self::RangeNotSatisfiable.to_string(),
140            417 => Self::ExpectationFailed.to_string(),
141            418 => Self::ImATeapot.to_string(),
142            421 => Self::MisdirectedRequest.to_string(),
143            422 => Self::UnprocessableEntity.to_string(),
144            423 => Self::Locked.to_string(),
145            424 => Self::FailedDependency.to_string(),
146            425 => Self::TooEarly.to_string(),
147            426 => Self::UpgradeRequired.to_string(),
148            428 => Self::PreconditionRequired.to_string(),
149            429 => Self::TooManyRequests.to_string(),
150            431 => Self::RequestHeaderFieldsTooLarge.to_string(),
151            451 => Self::UnavailableForLegalReasons.to_string(),
152            500 => Self::InternalServerError.to_string(),
153            501 => Self::NotImplemented.to_string(),
154            502 => Self::BadGateway.to_string(),
155            503 => Self::ServiceUnavailable.to_string(),
156            504 => Self::GatewayTimeout.to_string(),
157            505 => Self::HTTPVersionNotSupported.to_string(),
158            506 => Self::VariantAlsoNegotiates.to_string(),
159            507 => Self::InsufficientStorage.to_string(),
160            508 => Self::LoopDetected.to_string(),
161            510 => Self::NotExtended.to_string(),
162            511 => Self::NetworkAuthenticationRequired.to_string(),
163            _ => Self::Unknown.to_string(),
164        }
165    }
166
167    /// Checks if status matches a string representation.
168    ///
169    /// Compares case-insensitively against both numeric code and text description.
170    ///
171    /// # Arguments
172    ///
173    /// - `&self` - The HttpStatus instance.
174    /// - `&str` - The string to compare against.
175    ///
176    /// # Returns
177    ///
178    /// - `bool` - True if the string matches either code or description.
179    pub fn same(&self, code_str: &str) -> bool {
180        self.to_string().eq_ignore_ascii_case(code_str)
181    }
182}
183
184/// Implements the `Display` trait for `HttpStatus`, allowing it to be formatted as a string.
185impl Display for HttpStatus {
186    /// Formats the status code as text.
187    ///
188    /// # Arguments
189    ///
190    /// - `&mut fmt::Formatter` - The formatter to write to.
191    ///
192    /// # Returns
193    ///
194    /// - `fmt::Result` - The formatting result.
195    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
196        let res: &str = match self {
197            Self::Continue => CONTINUE,
198            Self::SwitchingProtocols => SWITCHING_PROTOCOLS,
199            Self::Processing => PROCESSING,
200            Self::EarlyHints => EARLY_HINTS,
201            Self::Ok => OK,
202            Self::Created => CREATED,
203            Self::Accepted => ACCEPTED,
204            Self::NonAuthoritativeInformation => NON_AUTHORITATIVE_INFORMATION,
205            Self::NoContent => NO_CONTENT,
206            Self::ResetContent => RESET_CONTENT,
207            Self::PartialContent => PARTIAL_CONTENT,
208            Self::MultiStatus => MULTI_STATUS,
209            Self::AlreadyReported => ALREADY_REPORTED,
210            Self::IMUsed => IM_USED,
211            Self::MultipleChoices => MULTIPLE_CHOICES,
212            Self::MovedPermanently => MOVED_PERMANENTLY,
213            Self::Found => FOUND,
214            Self::SeeOther => SEE_OTHER,
215            Self::NotModified => NOT_MODIFIED,
216            Self::UseProxy => USE_PROXY,
217            Self::TemporaryRedirect => TEMPORARY_REDIRECT,
218            Self::PermanentRedirect => PERMANENT_REDIRECT,
219            Self::BadRequest => BAD_REQUEST,
220            Self::Unauthorized => UNAUTHORIZED,
221            Self::PaymentRequired => PAYMENT_REQUIRED,
222            Self::Forbidden => FORBIDDEN,
223            Self::NotFound => NOT_FOUND,
224            Self::MethodNotAllowed => METHOD_NOT_ALLOWED,
225            Self::NotAcceptable => NOT_ACCEPTABLE,
226            Self::ProxyAuthenticationRequired => PROXY_AUTHENTICATION_REQUIRED,
227            Self::RequestTimeout => REQUEST_TIMEOUT,
228            Self::Conflict => CONFLICT,
229            Self::Gone => GONE,
230            Self::LengthRequired => LENGTH_REQUIRED,
231            Self::PreconditionFailed => PRECONDITION_FAILED,
232            Self::PayloadTooLarge => PAYLOAD_TOO_LARGE,
233            Self::URITooLong => URI_TOO_LONG,
234            Self::UnsupportedMediaType => UNSUPPORTED_MEDIA_TYPE,
235            Self::RangeNotSatisfiable => RANGE_NOT_SATISFIABLE,
236            Self::ExpectationFailed => EXPECTATION_FAILED,
237            Self::ImATeapot => IM_A_TEAPOT,
238            Self::MisdirectedRequest => MISDIRECTED_REQUEST,
239            Self::UnprocessableEntity => UNPROCESSABLE_ENTITY,
240            Self::Locked => LOCKED,
241            Self::FailedDependency => FAILED_DEPENDENCY,
242            Self::TooEarly => TOO_EARLY,
243            Self::UpgradeRequired => UPGRADE_REQUIRED,
244            Self::PreconditionRequired => PRECONDITION_REQUIRED,
245            Self::TooManyRequests => TOO_MANY_REQUESTS,
246            Self::RequestHeaderFieldsTooLarge => REQUEST_HEADER_FIELDS_TOO_LARGE,
247            Self::UnavailableForLegalReasons => UNAVAILABLE_FOR_LEGAL_REASONS,
248            Self::InternalServerError => INTERNAL_SERVER_ERROR,
249            Self::NotImplemented => NOT_IMPLEMENTED,
250            Self::BadGateway => BAD_GATEWAY,
251            Self::ServiceUnavailable => SERVICE_UNAVAILABLE,
252            Self::GatewayTimeout => GATEWAY_TIMEOUT,
253            Self::HTTPVersionNotSupported => HTTP_VERSION_NOT_SUPPORTED,
254            Self::VariantAlsoNegotiates => VARIANT_ALSO_NEGOTIATES,
255            Self::InsufficientStorage => INSUFFICIENT_STORAGE,
256            Self::LoopDetected => LOOP_DETECTED,
257            Self::NotExtended => NOT_EXTENDED,
258            Self::NetworkAuthenticationRequired => NETWORK_AUTHENTICATION_REQUIRED,
259            Self::Unknown => UNKNOWN,
260        };
261        write!(f, "{}", res)
262    }
263}
264
265/// Implements the `FromStr` trait for `HttpStatus`, allowing conversion from a string slice.
266impl FromStr for HttpStatus {
267    /// The error type returned when conversion fails.
268    type Err = ();
269
270    /// Parses a string into an HttpStatus.
271    ///
272    /// Attempts to convert the string to a numeric code and match known status codes.
273    ///
274    /// # Arguments
275    ///
276    /// - `&str` - The string to parse.
277    ///
278    /// # Returns
279    ///
280    /// - `Result<HttpStatus, ()>` - The parsed status or error.
281    fn from_str(code_str: &str) -> Result<Self, Self::Err> {
282        if let Ok(code) = code_str.parse::<ResponseStatusCode>() {
283            match code {
284                100 => Ok(Self::Continue),
285                101 => Ok(Self::SwitchingProtocols),
286                102 => Ok(Self::Processing),
287                103 => Ok(Self::EarlyHints),
288                200 => Ok(Self::Ok),
289                201 => Ok(Self::Created),
290                202 => Ok(Self::Accepted),
291                203 => Ok(Self::NonAuthoritativeInformation),
292                204 => Ok(Self::NoContent),
293                205 => Ok(Self::ResetContent),
294                206 => Ok(Self::PartialContent),
295                207 => Ok(Self::MultiStatus),
296                208 => Ok(Self::AlreadyReported),
297                226 => Ok(Self::IMUsed),
298                300 => Ok(Self::MultipleChoices),
299                301 => Ok(Self::MovedPermanently),
300                302 => Ok(Self::Found),
301                303 => Ok(Self::SeeOther),
302                304 => Ok(Self::NotModified),
303                305 => Ok(Self::UseProxy),
304                307 => Ok(Self::TemporaryRedirect),
305                308 => Ok(Self::PermanentRedirect),
306                400 => Ok(Self::BadRequest),
307                401 => Ok(Self::Unauthorized),
308                402 => Ok(Self::PaymentRequired),
309                403 => Ok(Self::Forbidden),
310                404 => Ok(Self::NotFound),
311                405 => Ok(Self::MethodNotAllowed),
312                406 => Ok(Self::NotAcceptable),
313                407 => Ok(Self::ProxyAuthenticationRequired),
314                408 => Ok(Self::RequestTimeout),
315                409 => Ok(Self::Conflict),
316                410 => Ok(Self::Gone),
317                411 => Ok(Self::LengthRequired),
318                412 => Ok(Self::PreconditionFailed),
319                413 => Ok(Self::PayloadTooLarge),
320                414 => Ok(Self::URITooLong),
321                415 => Ok(Self::UnsupportedMediaType),
322                416 => Ok(Self::RangeNotSatisfiable),
323                417 => Ok(Self::ExpectationFailed),
324                418 => Ok(Self::ImATeapot),
325                421 => Ok(Self::MisdirectedRequest),
326                422 => Ok(Self::UnprocessableEntity),
327                423 => Ok(Self::Locked),
328                424 => Ok(Self::FailedDependency),
329                425 => Ok(Self::TooEarly),
330                426 => Ok(Self::UpgradeRequired),
331                428 => Ok(Self::PreconditionRequired),
332                429 => Ok(Self::TooManyRequests),
333                431 => Ok(Self::RequestHeaderFieldsTooLarge),
334                451 => Ok(Self::UnavailableForLegalReasons),
335                500 => Ok(Self::InternalServerError),
336                501 => Ok(Self::NotImplemented),
337                502 => Ok(Self::BadGateway),
338                503 => Ok(Self::ServiceUnavailable),
339                504 => Ok(Self::GatewayTimeout),
340                505 => Ok(Self::HTTPVersionNotSupported),
341                506 => Ok(Self::VariantAlsoNegotiates),
342                507 => Ok(Self::InsufficientStorage),
343                508 => Ok(Self::LoopDetected),
344                510 => Ok(Self::NotExtended),
345                511 => Ok(Self::NetworkAuthenticationRequired),
346                _ => Ok(Self::Unknown),
347            }
348        } else {
349            Ok(Self::Unknown)
350        }
351    }
352}
353
354/// Implements the `Default` trait for `HttpStatus`.
355impl Default for HttpStatus {
356    /// Gets the default HTTP status code.
357    ///
358    /// # Returns
359    ///
360    /// - `HttpStatus` - The default status.
361    fn default() -> Self {
362        Self::Unknown
363    }
364}