ogn_parser/
server_comment.rs1use std::net::IpAddr;
2use std::str::FromStr;
3
4use chrono::prelude::*;
5use serde::Serialize;
6
7use crate::AprsError;
8
9#[derive(PartialEq, Debug, Clone, Serialize)]
10pub struct ServerComment {
11 pub version: String,
12 pub timestamp: DateTime<Utc>,
13 pub server: String,
14 pub ip_address: IpAddr,
15 pub port: u16,
16}
17
18impl FromStr for ServerComment {
19 type Err = AprsError;
20
21 fn from_str(s: &str) -> Result<Self, Self::Err> {
22 let mut parts = s.split_whitespace();
23
24 if parts.next() != Some("#") || parts.next() != Some("aprsc") {
26 return Err(AprsError::InvalidServerComment(s.to_string()));
27 }
28
29 let version = parts
31 .next()
32 .ok_or_else(|| AprsError::InvalidServerComment(s.to_string()))?;
33
34 let timestamp_str = parts.by_ref().take(5).collect::<Vec<_>>().join(" ");
36 let timestamp = DateTime::parse_from_rfc2822(×tamp_str)
37 .map_err(|_| AprsError::InvalidServerComment(s.to_string()))?
38 .with_timezone(&Utc);
39
40 let server = parts
42 .next()
43 .ok_or_else(|| AprsError::InvalidServerComment(s.to_string()))?;
44
45 let address = parts
47 .next()
48 .ok_or_else(|| AprsError::InvalidServerComment(s.to_string()))?;
49 let (ip_address, port) = address
50 .split_once(':')
51 .ok_or_else(|| AprsError::InvalidServerComment(address.to_string()))?;
52 let ip_address = ip_address
53 .parse::<IpAddr>()
54 .map_err(|_| AprsError::InvalidServerComment(s.to_string()))?;
55 let port = port
56 .parse::<u16>()
57 .map_err(|_| AprsError::InvalidServerComment(s.to_string()))?;
58
59 Ok(ServerComment {
60 version: version.to_string(),
61 timestamp,
62 server: server.to_string(),
63 ip_address,
64 port,
65 })
66 }
67}
68
69#[cfg(test)]
70mod tests {
71 use super::*;
72 use std::net::{IpAddr, Ipv4Addr};
73
74 #[test]
75 fn test_server_comment() {
76 let raw_message =
77 r"# aprsc 2.1.4-g408ed49 17 Mar 2018 09:30:36 GMT GLIDERN1 37.187.40.234:10152";
78 let result = raw_message.parse::<ServerComment>().unwrap();
79
80 assert_eq!(result.version, "2.1.4-g408ed49");
81 assert_eq!(
82 result.timestamp.to_string(),
83 "2018-03-17 09:30:36 UTC".to_string()
84 );
85 assert_eq!(result.server, "GLIDERN1");
86 assert_eq!(
87 result.ip_address,
88 IpAddr::V4(Ipv4Addr::new(37, 187, 40, 234))
89 );
90 assert_eq!(result.port, 10152);
91 }
92}