use crate::error::AprsError;
use crate::types::Timestamp;
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct AprsStatus {
pub timestamp: Option<Timestamp>,
pub comment: Vec<u8>,
}
impl AprsStatus {
pub(crate) fn parse(info: &[u8]) -> Result<Self, AprsError> {
let b = info.get(1..).unwrap_or_default();
let timestamp = b.get(..7).and_then(|ts| Timestamp::parse(ts).ok());
let comment = if timestamp.is_some() {
b.get(7..).unwrap_or_default().to_vec()
} else {
b.to_vec()
};
Ok(Self { timestamp, comment })
}
pub fn encode(&self) -> Vec<u8> {
let mut out = vec![b'>'];
if let Some(ref ts) = self.timestamp {
ts.encode(&mut out);
}
out.extend_from_slice(&self.comment);
out
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn no_timestamp_no_comment() {
let s = AprsStatus::parse(b">").unwrap();
assert!(s.timestamp.is_none());
assert!(s.comment.is_empty());
}
#[test]
fn with_ddhhmm_timestamp() {
let s = AprsStatus::parse(b">312359zSystem online").unwrap();
assert_eq!(s.timestamp, Some(Timestamp::Ddhhmm(31, 23, 59)));
assert_eq!(s.comment, b"System online");
}
#[test]
fn with_hhmmss_timestamp() {
let s = AprsStatus::parse(b">235959hHi there!").unwrap();
assert_eq!(s.timestamp, Some(Timestamp::Hhmmss(23, 59, 59)));
assert_eq!(s.comment, b"Hi there!");
}
#[test]
fn no_timestamp_with_comment() {
let s = AprsStatus::parse(b">12.6V 0.2A 22degC").unwrap();
assert!(s.timestamp.is_none());
assert_eq!(s.comment, b"12.6V 0.2A 22degC");
}
#[test]
fn encode_round_trip() {
for raw in [
b">312359zSystem online".as_slice(),
b">Hi there!".as_slice(),
b">".as_slice(),
] {
let s = AprsStatus::parse(raw).unwrap();
assert_eq!(s.encode(), raw);
}
}
}