pub trait StatusCode {
fn is_http_ok(&self) -> bool;
fn is_http_err(&self) -> bool;
fn is_user_err(&self) -> bool;
fn is_server_err(&self) -> bool;
fn status_msg(&self) -> &'static str;
}
macro_rules! into {
($e:expr) => {
<Self as TryInto<u64>>::try_into(*$e)
};
}
impl<T: TryInto<u64> + Copy> StatusCode for T {
#[inline]
fn is_http_ok(&self) -> bool {
into!(self).is_ok_and(|n| (200..300).contains(&n))
}
#[inline]
fn is_user_err(&self) -> bool {
into!(self).is_ok_and(|n| (400..500).contains(&n))
}
#[inline]
fn is_server_err(&self) -> bool {
into!(self).is_ok_and(|n| (500..600).contains(&n))
}
#[inline]
fn is_http_err(&self) -> bool {
!self.is_http_ok()
}
fn status_msg(&self) -> &'static str {
let Ok(n) = into!(self) else {
return "?";
};
match n {
200 => "OK",
201 => "CREATED",
202 => "ACCEPTED",
203 => "NON-AUTHORITATIVE INFORMATION",
204 => "NO CONTENT",
205 => "RESET CONTENT",
206 => "PARTIAL CONTENT",
300 => "MULTIPLE CHOICES",
301 => "MOVED PERMANENTLY",
302 => "FOUND",
303 => "SEE OTHER",
304 => "NOT MODIFIED",
307 => "TEMPORARY REDIRECT",
308 => "PERMANENT REDIRECT",
400 => "BAD REQUEST",
401 => "UNAUTHORIZED",
403 => "FORBIDDEN",
404 => "NOT FOUND",
405 => "METHOD NOT ALLOWED",
406 => "NOT ACCEPTABLE",
407 => "PROXY AUTHENTICATION REQUIRED",
408 => "REQUEST TIMEOUT",
409 => "CONFLICT",
410 => "GONE",
411 => "LENGTH REQUIRED",
412 => "PRECONDITION FAILED",
413 => "PAYLOAD TOO LARGE",
414 => "URI TOO LONG",
415 => "UNSUPPORTED MEDIA TYPE",
416 => "REQUESTED RANGE NOT SATISFIABLE",
429 => "TOO MANY REQUESTS",
501 => "NOT IMPLEMENTED",
500 => "INTERNAL SERVER ERROR",
_ => "?",
}
}
}
#[cfg(test)]
mod test {
use super::StatusCode;
#[test]
fn code_test() {
for n in 200..300 {
assert!(n.is_http_ok());
assert!(!n.is_http_err());
}
assert!(!300.is_http_ok());
assert!(510.is_server_err());
assert!(!600.is_server_err());
}
}