http/
status.rs

1pub trait StatusCode {
2    /// Returns true if the status code of the
3    /// request represents an OK status (200-300)
4    fn is_http_ok(&self) -> bool;
5    /// Returns true if the status code of the
6    /// request doesn't represent an OK status (200-300)
7    fn is_http_err(&self) -> bool;
8
9    /// Returns true if the status code
10    /// indicates am user error (4XX)
11    fn is_user_err(&self) -> bool;
12    /// Returns true if the status code
13    /// indicates a server error (5XX)
14    fn is_server_err(&self) -> bool;
15    /// Get a human-readable description of the request's status code
16    fn status_msg(&self) -> &'static str;
17}
18
19macro_rules! into {
20    ($e:expr) => {
21        <Self as TryInto<u64>>::try_into(*$e)
22    };
23}
24
25impl<T: TryInto<u64> + Copy> StatusCode for T {
26    #[inline]
27    fn is_http_ok(&self) -> bool {
28        into!(self).is_ok_and(|n| (200..300).contains(&n))
29    }
30    #[inline]
31    fn is_user_err(&self) -> bool {
32        into!(self).is_ok_and(|n| (400..500).contains(&n))
33    }
34    #[inline]
35    fn is_server_err(&self) -> bool {
36        into!(self).is_ok_and(|n| (500..600).contains(&n))
37    }
38    #[inline]
39    fn is_http_err(&self) -> bool {
40        !self.is_http_ok()
41    }
42
43    fn status_msg(&self) -> &'static str {
44        let Ok(n) = into!(self) else {
45            return "?";
46        };
47        match n {
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            300 => "MULTIPLE CHOICES",
56            301 => "MOVED PERMANENTLY",
57            302 => "FOUND",
58            303 => "SEE OTHER",
59            304 => "NOT MODIFIED",
60            307 => "TEMPORARY REDIRECT",
61            308 => "PERMANENT REDIRECT",
62            400 => "BAD REQUEST",
63            401 => "UNAUTHORIZED",
64            403 => "FORBIDDEN",
65            404 => "NOT FOUND",
66            405 => "METHOD NOT ALLOWED",
67            406 => "NOT ACCEPTABLE",
68            407 => "PROXY AUTHENTICATION REQUIRED",
69            408 => "REQUEST TIMEOUT",
70            409 => "CONFLICT",
71            410 => "GONE",
72            411 => "LENGTH REQUIRED",
73            412 => "PRECONDITION FAILED",
74            413 => "PAYLOAD TOO LARGE",
75            414 => "URI TOO LONG",
76            415 => "UNSUPPORTED MEDIA TYPE",
77            416 => "REQUESTED RANGE NOT SATISFIABLE",
78            429 => "TOO MANY REQUESTS",
79            501 => "NOT IMPLEMENTED",
80            500 => "INTERNAL SERVER ERROR",
81            _ => "?",
82        }
83    }
84}
85
86#[cfg(test)]
87mod test {
88    use super::StatusCode;
89
90    #[test]
91    fn code_test() {
92        for n in 200..300 {
93            assert!(n.is_http_ok());
94            assert!(!n.is_http_err());
95        }
96        assert!(!300.is_http_ok());
97        assert!(510.is_server_err());
98        assert!(!600.is_server_err());
99    }
100}