dory/src/response.rs

105 lines
2.7 KiB
Rust
Raw Normal View History

use std::{fmt, num::ParseIntError, str::FromStr};
2023-05-22 01:29:03 -04:00
2023-05-22 18:11:14 -04:00
use crate::status::{ParseStatusError, Status};
2023-05-22 01:29:03 -04:00
#[derive(Clone, Debug, PartialEq)]
pub struct Response {
pub status: Status,
pub meta: String,
}
impl fmt::Display for Response {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{} {}\r\n", u8::from(self.status.clone()), self.meta)
}
}
#[derive(Clone, Debug, PartialEq)]
pub enum ParseResponseError {
TooLong,
ParseInt(ParseIntError),
StatusError,
Malformed,
}
impl fmt::Display for ParseResponseError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::TooLong => write!(f, "ParseResponseError: too long"),
Self::ParseInt(e) => write!(f, "ParseResponseError: {e}"),
Self::StatusError => write!(f, "ParseResponseError: Invalid Status"),
Self::Malformed => write!(f, "ParseResponseError: Malformed"),
}
}
}
impl std::error::Error for ParseResponseError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
Self::ParseInt(e) => Some(e),
_ => None,
}
}
}
impl From<ParseIntError> for ParseResponseError {
fn from(value: ParseIntError) -> Self {
Self::ParseInt(value)
}
}
impl From<ParseStatusError> for ParseResponseError {
fn from(_value: ParseStatusError) -> Self {
2023-05-22 01:29:03 -04:00
Self::StatusError
}
}
impl FromStr for Response {
type Err = ParseResponseError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
if s.len() > 2048 {
return Err(ParseResponseError::TooLong);
}
if !s.ends_with("\r\n") {
return Err(ParseResponseError::Malformed);
}
let Some((status, meta)) = s.split_once(' ') else {
return Err(ParseResponseError::Malformed);
};
let status: u8 = status.parse()?;
let status: Status = status.try_into()?;
Ok(Self {
status,
meta: meta.trim_end().to_string(),
})
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn parse_success() {
let response: Response = "20 message delivered\r\n".parse().unwrap();
assert_eq!(response.status, Status::Success);
assert_eq!(response.meta.as_str(), "message delivered");
}
#[test]
fn parse_badend() {
let response = "20 message delivered\n".parse::<Response>();
assert_eq!(response, Err(ParseResponseError::Malformed));
}
#[test]
fn parse_badint() {
let response = "twenty message deliverred\r\n".parse::<Response>();
match response {
Err(ParseResponseError::ParseInt(_)) => {}
_ => panic!(),
}
}
2023-05-22 01:29:03 -04:00
}