Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support accessing the response code as an integer #70

Merged
merged 3 commits into from
May 14, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 91 additions & 3 deletions src/response/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ where
/// The method used to create the response.
method: Method,
/// The HTTP response status code.
pub status: Status,
pub status: StatusCode,
/// The HTTP response content type.
pub content_type: Option<ContentType>,
/// The content length.
Expand Down Expand Up @@ -383,7 +383,42 @@ where
}
}

/// HTTP status types
/// An HTTP status code.
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct StatusCode(pub u16);

impl From<u16> for StatusCode {
fn from(value: u16) -> Self {
Self(value)
}
}

/// An error returned when trying to convert Status::Unknown into a StatusCode
#[derive(Debug)]
pub struct UnknownStatusError;

impl TryFrom<Status> for StatusCode {
type Error = UnknownStatusError;

fn try_from(from: Status) -> Result<StatusCode, UnknownStatusError> {
match from {
Status::Unknown => Err(UnknownStatusError),
_ => Ok(StatusCode(from as u16)),
}
}
}

impl PartialEq<Status> for StatusCode {
fn eq(&self, rhs: &Status) -> bool {
match rhs {
Status::Unknown => false,
_ => self.0 == (*rhs as u16),
}
}
}

/// Enumeration of well-known HTTP status codes
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum Status {
Expand Down Expand Up @@ -441,9 +476,21 @@ impl Status {
}
}

impl PartialEq<StatusCode> for Status {
fn eq(&self, rhs: &StatusCode) -> bool {
rhs == self
}
}

impl From<u16> for Status {
fn from(from: u16) -> Status {
match from {
StatusCode(from).into()
}
}

impl From<StatusCode> for Status {
fn from(from: StatusCode) -> Status {
match from.0 {
200 => Status::Ok,
201 => Status::Created,
202 => Status::Accepted,
Expand Down Expand Up @@ -483,6 +530,7 @@ mod tests {
use embedded_io::ErrorType;
use embedded_io_async::Read;

use super::{Status, StatusCode};
use crate::{
reader::BufferingReader,
request::Method,
Expand Down Expand Up @@ -750,4 +798,44 @@ mod tests {
}

impl TryBufRead for FakeSingleReadConnection {}

#[test]
fn status_equality() {
// StatusCode and Status values can be compared
assert_eq!(StatusCode(200), Status::Ok);
assert_eq!(Status::Ok, StatusCode(200));
assert_eq!(StatusCode(404), Status::NotFound);
assert_eq!(Status::NotFound, StatusCode(404));
assert_ne!(Status::Ok, StatusCode(404));

// Status::Unknown does not compare as equal to any StatusCode value
assert_ne!(Status::Unknown, StatusCode(0));
assert_ne!(StatusCode(0), Status::Unknown);

// StatusCode supports comparison of arbitrary values
assert_eq!(StatusCode(0), StatusCode(0));
assert_eq!(StatusCode(987), StatusCode(987));
assert_ne!(StatusCode(123), StatusCode(321));
}

#[test]
fn status_try_from() {
let s: Status = 200.into();
assert_eq!(Status::Ok, s);
let s: Status = StatusCode(500).try_into().unwrap();
assert_eq!(Status::InternalServerError, s);
let s: StatusCode = Status::NotModified.try_into().unwrap();
assert_eq!(s, StatusCode(304));

// Unknown status code values can be converted into Status::Unknown
let im_a_teapot: Status = StatusCode(418).into();
assert_eq!(Status::Unknown, im_a_teapot);
let im_a_teapot: Status = 418.into();
assert_eq!(Status::Unknown, im_a_teapot);

// Converting Status::Unknown back to a StatusCode will fail
<Status as TryInto<StatusCode>>::try_into(Status::Unknown).expect_err("Status::Unknown conversion should fail");
<Status as TryInto<StatusCode>>::try_into(StatusCode(418).into())
.expect_err("Status::Unknown conversion should fail");
}
}
Loading