use super::InvalidStatusCode;
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct StatusCode(u16);
impl StatusCode {
#[inline]
pub fn to_u16(self) -> u16 {
self.0
}
#[inline]
pub fn try_from_u16(code: u16) -> Result<Self, InvalidStatusCode> {
if is_valid_status_code(code) {
Ok(Self(code))
} else {
Err(InvalidStatusCode { code })
}
}
pub(super) const fn internal_from_const_u16(code: u16) -> Self {
if !is_valid_status_code(code) {
#[allow(unconditional_panic, clippy::no_effect)]
([] as [u8; 0])[0]; }
Self(code)
}
pub fn is_informational(self) -> bool {
matches!(self.to_u16(), 100..=199)
}
pub fn is_successful(self) -> bool {
matches!(self.to_u16(), 200..=299)
}
pub fn is_redirection(self) -> bool {
matches!(self.to_u16(), 300..=399)
}
pub fn is_client_error(self) -> bool {
matches!(self.to_u16(), 400..=499)
}
pub fn is_server_error(self) -> bool {
matches!(self.to_u16(), 500..=599)
}
}
impl Default for StatusCode {
fn default() -> Self {
Self::OK
}
}
impl From<StatusCode> for u16 {
#[inline]
fn from(s: StatusCode) -> Self {
s.to_u16()
}
}
impl PartialEq<u16> for StatusCode {
#[inline]
fn eq(&self, other: &u16) -> bool {
self.to_u16().eq(other)
}
}
impl PartialOrd<u16> for StatusCode {
#[inline]
fn partial_cmp(&self, other: &u16) -> Option<std::cmp::Ordering> {
self.to_u16().partial_cmp(other)
}
}
const fn is_valid_status_code(code: u16) -> bool {
matches!(code, 100..=599)
}
#[cfg(test)]
mod tests {
use super::*;
use assert_matches::assert_matches;
#[test]
fn generated_constants_are_valid() {
for constant in StatusCode::GENERATED_CONSTANTS.iter().map(|c| c.to_u16()) {
assert_matches!(StatusCode::try_from_u16(constant), Ok(x) => assert_eq!(x, constant));
}
}
}