ogn_parser/
callsign.rs

1use std::fmt::{Display, Formatter};
2use std::str::FromStr;
3
4use serde::Serialize;
5
6use crate::AprsError;
7
8#[derive(Eq, PartialEq, Debug, Clone, Serialize)]
9#[serde(into = "String")]
10pub struct Callsign {
11    pub call: String,
12    pub ssid: Option<u8>,
13}
14
15impl From<Callsign> for String {
16    fn from(val: Callsign) -> Self {
17        if let Some(ssid) = val.ssid {
18            format!("{}-{}", val.call, ssid)
19        } else {
20            val.call
21        }
22    }
23}
24
25impl Callsign {
26    pub fn new<T: Into<String>>(call: T, ssid: Option<u8>) -> Callsign {
27        Callsign {
28            call: call.into(),
29            ssid,
30        }
31    }
32}
33
34impl FromStr for Callsign {
35    type Err = AprsError;
36
37    fn from_str(s: &str) -> Result<Self, <Self as FromStr>::Err> {
38        let delimiter = s.find('-'); //.ok_or_else(|| AprsError::EmptyCallsign(s.to_owned()))?;
39        if delimiter.is_none() {
40            return Ok(Callsign::new(s, None));
41        }
42
43        let delimiter = delimiter.unwrap();
44        if delimiter == 0 {
45            return Err(AprsError::EmptyCallsign(s.to_owned()));
46        }
47
48        let (call, rest) = s.split_at(delimiter);
49        let part = &rest[1..rest.len()];
50
51        if part.is_empty() {
52            return Err(AprsError::EmptySSID(s.to_owned()));
53        }
54
55        let ssid = part.parse::<u8>().ok();
56
57        if ssid.is_some() {
58            Ok(Callsign::new(call, ssid))
59        } else {
60            Err(AprsError::InvalidSSID(s.to_owned()))
61        }
62    }
63}
64
65impl Display for Callsign {
66    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
67        write!(f, "{}", self.call)?;
68
69        if let Some(ssid) = &self.ssid {
70            write!(f, "-{}", ssid)?;
71        }
72
73        Ok(())
74    }
75}
76
77#[cfg(test)]
78mod tests {
79    use super::*;
80
81    #[test]
82    fn parse_callsign() {
83        assert_eq!("ABCDEF".parse(), Ok(Callsign::new("ABCDEF", None)));
84    }
85
86    #[test]
87    fn parse_with_ssid() {
88        assert_eq!("ABCDEF-42".parse(), Ok(Callsign::new("ABCDEF", Some(42))));
89    }
90
91    #[test]
92    fn empty_callsign() {
93        assert_eq!(
94            "-42".parse::<Callsign>(),
95            Err(AprsError::EmptyCallsign("-42".to_owned()))
96        );
97    }
98
99    #[test]
100    fn empty_ssid() {
101        assert_eq!(
102            "ABCDEF-".parse::<Callsign>(),
103            Err(AprsError::EmptySSID("ABCDEF-".to_owned()))
104        );
105    }
106
107    #[test]
108    fn invalid_ssid() {
109        assert_eq!(
110            "D-EKDF".parse::<Callsign>(),
111            Err(AprsError::InvalidSSID("D-EKDF".to_owned()))
112        );
113    }
114}