use std::fmt::{Display, Formatter};
use std::str::FromStr;
use serde::Serialize;
use crate::AprsError;
use crate::Timestamp;
use crate::status_comment::StatusComment;
#[derive(PartialEq, Debug, Clone, Serialize)]
pub struct AprsStatus {
#[serde(skip_serializing_if = "Option::is_none")]
pub timestamp: Option<Timestamp>,
#[serde(flatten)]
pub comment: StatusComment,
}
impl FromStr for AprsStatus {
type Err = AprsError;
fn from_str(s: &str) -> Result<Self, <Self as FromStr>::Err> {
let timestamp = if s.len() >= 7 {
s[0..7].parse::<Timestamp>().ok()
} else {
None
};
let comment = if timestamp.is_some() { &s[7..] } else { s };
Ok(AprsStatus {
timestamp,
comment: comment.parse::<StatusComment>().unwrap(),
})
}
}
impl Display for AprsStatus {
fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
write!(f, ">")?;
if let Some(ts) = &self.timestamp {
write!(f, "{ts}")?;
}
write!(f, "{:#?}", self.comment)?;
Ok(())
}
}
#[cfg(test)]
mod tests {
use csv::WriterBuilder;
use std::io::stdout;
use super::*;
#[test]
fn parse_without_timestamp_or_comment() {
let result = "".parse::<AprsStatus>().unwrap();
assert_eq!(result.timestamp, None);
assert_eq!(result.comment, StatusComment::default());
}
#[test]
fn parse_with_timestamp_without_comment() {
let result = "312359z".parse::<AprsStatus>().unwrap();
assert_eq!(result.timestamp, Some(Timestamp::DDHHMM(31, 23, 59)));
assert_eq!(result.comment, StatusComment::default());
}
#[test]
fn parse_without_timestamp_with_comment() {
let result = "Hi there!".parse::<AprsStatus>().unwrap();
assert_eq!(result.timestamp, None);
assert_eq!(result.comment.unparsed.unwrap(), "Hi there!");
}
#[test]
fn parse_with_timestamp_and_comment() {
let result = "235959hHi there!".parse::<AprsStatus>().unwrap();
assert_eq!(result.timestamp, Some(Timestamp::HHMMSS(23, 59, 59)));
assert_eq!(result.comment.unparsed.unwrap(), "Hi there!");
}
#[ignore = "status_comment serialization not implemented"]
#[test]
fn test_serialize() {
let aprs_position = "235959hHi there!".parse::<AprsStatus>().unwrap();
let mut wtr = WriterBuilder::new().from_writer(stdout());
wtr.serialize(aprs_position).unwrap();
wtr.flush().unwrap();
}
}