1use std::fmt::{Display, Formatter};
2use std::str::FromStr;
3
4use crate::AprsError;
5use serde::Serialize;
6
7#[derive(Eq, PartialEq, Debug, Clone)]
8pub enum Timestamp {
9 DDHHMM(u8, u8, u8),
11 HHMMSS(u8, u8, u8),
13 Unsupported(String),
15}
16
17impl FromStr for Timestamp {
18 type Err = AprsError;
19
20 fn from_str(s: &str) -> Result<Self, <Self as FromStr>::Err> {
21 let b = s.as_bytes();
22
23 if b.len() != 7 {
24 return Err(AprsError::InvalidTimestamp(s.to_owned()));
25 }
26
27 let one = s[0..2]
28 .parse::<u8>()
29 .map_err(|_| AprsError::InvalidTimestamp(s.to_owned()))?;
30 let two = s[2..4]
31 .parse::<u8>()
32 .map_err(|_| AprsError::InvalidTimestamp(s.to_owned()))?;
33 let three = s[4..6]
34 .parse::<u8>()
35 .map_err(|_| AprsError::InvalidTimestamp(s.to_owned()))?;
36
37 Ok(match b[6] as char {
38 'z' => Timestamp::DDHHMM(one, two, three),
39 'h' => Timestamp::HHMMSS(one, two, three),
40 '/' => Timestamp::Unsupported(s.to_owned()),
41 _ => return Err(AprsError::InvalidTimestamp(s.to_owned())),
42 })
43 }
44}
45
46impl Display for Timestamp {
47 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
48 match self {
49 Self::DDHHMM(d, h, m) => write!(f, "{:02}{:02}{:02}z", d, h, m),
50 Self::HHMMSS(h, m, s) => write!(f, "{:02}{:02}{:02}h", h, m, s),
51 Self::Unsupported(s) => write!(f, "{}", s),
52 }
53 }
54}
55
56impl Serialize for Timestamp {
57 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
58 where
59 S: serde::Serializer,
60 {
61 serializer.serialize_str(&format!("{}", self))
62 }
63}
64
65#[cfg(test)]
66mod tests {
67 use csv::WriterBuilder;
68 use std::io::stdout;
69
70 use super::*;
71
72 #[test]
73 fn parse_ddhhmm() {
74 assert_eq!("123456z".parse(), Ok(Timestamp::DDHHMM(12, 34, 56)));
75 }
76
77 #[test]
78 fn parse_hhmmss() {
79 assert_eq!("123456h".parse(), Ok(Timestamp::HHMMSS(12, 34, 56)));
80 }
81
82 #[test]
83 fn parse_local_time() {
84 assert_eq!(
85 "123456/".parse::<Timestamp>(),
86 Ok(Timestamp::Unsupported("123456/".to_owned()))
87 );
88 }
89
90 #[test]
91 fn invalid_timestamp() {
92 assert_eq!(
93 "1234567".parse::<Timestamp>(),
94 Err(AprsError::InvalidTimestamp("1234567".to_owned()))
95 );
96 }
97
98 #[test]
99 fn invalid_timestamp2() {
100 assert_eq!(
101 "123a56z".parse::<Timestamp>(),
102 Err(AprsError::InvalidTimestamp("123a56z".to_owned()))
103 );
104 }
105
106 #[test]
107 fn test_serialize() {
108 let timestamp: Timestamp = "123456z".parse().unwrap();
109 let mut wtr = WriterBuilder::new().from_writer(stdout());
110 wtr.serialize(timestamp).unwrap();
111 wtr.flush().unwrap();
112 }
113}