1use super::InvalidStatusCode;
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
4pub struct StatusCode(u16);
5
6impl StatusCode {
7 #[inline]
8 pub fn to_u16(self) -> u16 {
9 self.0
10 }
11
12 #[inline]
13 pub fn try_from_u16(code: u16) -> Result<Self, InvalidStatusCode> {
14 if is_valid_status_code(code) {
15 Ok(Self(code))
16 } else {
17 Err(InvalidStatusCode { code })
18 }
19 }
20
21 pub(super) const fn internal_from_const_u16(code: u16) -> Self {
22 if !is_valid_status_code(code) {
23 #[allow(unconditional_panic, clippy::no_effect)]
24 ([] as [u8; 0])[0]; }
26 Self(code)
27 }
28
29 pub fn is_informational(self) -> bool {
30 matches!(self.to_u16(), 100..=199)
31 }
32
33 pub fn is_successful(self) -> bool {
34 matches!(self.to_u16(), 200..=299)
35 }
36
37 pub fn is_redirection(self) -> bool {
38 matches!(self.to_u16(), 300..=399)
39 }
40
41 pub fn is_client_error(self) -> bool {
42 matches!(self.to_u16(), 400..=499)
43 }
44
45 pub fn is_server_error(self) -> bool {
46 matches!(self.to_u16(), 500..=599)
47 }
48}
49
50impl Default for StatusCode {
51 fn default() -> Self {
52 Self::OK
53 }
54}
55
56impl From<StatusCode> for u16 {
57 #[inline]
58 fn from(s: StatusCode) -> Self {
59 s.to_u16()
60 }
61}
62
63impl PartialEq<u16> for StatusCode {
64 #[inline]
65 fn eq(&self, other: &u16) -> bool {
66 self.to_u16().eq(other)
67 }
68}
69
70impl PartialOrd<u16> for StatusCode {
71 #[inline]
72 fn partial_cmp(&self, other: &u16) -> Option<std::cmp::Ordering> {
73 self.to_u16().partial_cmp(other)
74 }
75}
76
77const fn is_valid_status_code(code: u16) -> bool {
78 matches!(code, 100..=599)
79}
80
81#[cfg(test)]
82mod tests {
83 use super::*;
84 use assert_matches::assert_matches;
85
86 #[test]
87 fn generated_constants_are_valid() {
88 for constant in StatusCode::GENERATED_CONSTANTS.iter().map(|c| c.to_u16()) {
89 assert_matches!(StatusCode::try_from_u16(constant), Ok(x) => assert_eq!(x, constant));
92 }
93 }
94}