1use crate::error::AprsError;
2use crate::types::Timestamp;
3
4#[derive(Debug, Clone, PartialEq, Eq)]
11#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
12pub struct AprsStatus {
13 pub timestamp: Option<Timestamp>,
15 pub comment: Vec<u8>,
16}
17
18impl AprsStatus {
19 pub(crate) fn parse(info: &[u8]) -> Result<Self, AprsError> {
21 let b = info.get(1..).unwrap_or_default();
23
24 let timestamp = b.get(..7).and_then(|ts| Timestamp::parse(ts).ok());
27 let comment = if timestamp.is_some() {
28 b.get(7..).unwrap_or_default().to_vec()
29 } else {
30 b.to_vec()
31 };
32
33 Ok(Self { timestamp, comment })
34 }
35
36 pub fn encode(&self) -> Vec<u8> {
37 let mut out = vec![b'>'];
38 if let Some(ref ts) = self.timestamp {
39 ts.encode(&mut out);
40 }
41 out.extend_from_slice(&self.comment);
42 out
43 }
44}
45
46#[cfg(test)]
47mod tests {
48 use super::*;
49
50 #[test]
51 fn no_timestamp_no_comment() {
52 let s = AprsStatus::parse(b">").unwrap();
53 assert!(s.timestamp.is_none());
54 assert!(s.comment.is_empty());
55 }
56
57 #[test]
58 fn with_ddhhmm_timestamp() {
59 let s = AprsStatus::parse(b">312359zSystem online").unwrap();
60 assert_eq!(s.timestamp, Some(Timestamp::Ddhhmm(31, 23, 59)));
61 assert_eq!(s.comment, b"System online");
62 }
63
64 #[test]
65 fn with_hhmmss_timestamp() {
66 let s = AprsStatus::parse(b">235959hHi there!").unwrap();
67 assert_eq!(s.timestamp, Some(Timestamp::Hhmmss(23, 59, 59)));
68 assert_eq!(s.comment, b"Hi there!");
69 }
70
71 #[test]
72 fn no_timestamp_with_comment() {
73 let s = AprsStatus::parse(b">12.6V 0.2A 22degC").unwrap();
74 assert!(s.timestamp.is_none());
75 assert_eq!(s.comment, b"12.6V 0.2A 22degC");
76 }
77
78 #[test]
79 fn encode_round_trip() {
80 for raw in [
81 b">312359zSystem online".as_slice(),
82 b">Hi there!".as_slice(),
83 b">".as_slice(),
84 ] {
85 let s = AprsStatus::parse(raw).unwrap();
86 assert_eq!(s.encode(), raw);
87 }
88 }
89}