igc/records/
d_record.rs

1use std::fmt;
2
3use crate::util::ParseError;
4
5#[derive(Debug, PartialEq, Eq)]
6pub enum GpsQualifier {
7    Gps,
8    DGps,
9}
10
11/// Differential GPS record - indicates that Differential GPS is being used.
12#[derive(Debug, PartialEq, Eq)]
13pub struct DRecord<'a> {
14    pub qualifier: GpsQualifier,
15    pub station_id: &'a str,
16}
17
18impl<'a> DRecord<'a> {
19    pub fn parse(line: &'a str) -> Result<Self, ParseError> {
20        if line.len() != 6 {
21            return Err(ParseError::SyntaxError);
22        }
23
24        let bytes = line.as_bytes();
25        assert_eq!(bytes[0], b'D');
26
27        let qualifier = match bytes[1] {
28            b'1' => GpsQualifier::Gps,
29            b'2' => GpsQualifier::DGps,
30            _ => return Err(ParseError::SyntaxError),
31        };
32
33        let station_id = &line[2..6];
34
35        Ok(DRecord {
36            qualifier,
37            station_id,
38        })
39    }
40}
41
42impl<'a> fmt::Display for DRecord<'a> {
43    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
44        let qual_str = match self.qualifier {
45            GpsQualifier::Gps => '1',
46            GpsQualifier::DGps => '2',
47        };
48
49        write!(f, "D{}{}", qual_str, self.station_id)
50    }
51}
52
53#[cfg(test)]
54mod tests {
55    use super::{DRecord, GpsQualifier};
56
57    #[test]
58    fn drecord_parse() {
59        let example_line = "D1ABCD";
60        let parsed = DRecord::parse(example_line).unwrap();
61        let expected = DRecord {
62            qualifier: GpsQualifier::Gps,
63            station_id: "ABCD",
64        };
65
66        assert_eq!(parsed, expected);
67    }
68
69    #[test]
70    fn drecord_format() {
71        let expected_string = "D1ABCD";
72        let record = DRecord {
73            qualifier: GpsQualifier::Gps,
74            station_id: "ABCD",
75        };
76
77        assert_eq!(format!("{}", record), expected_string);
78    }
79
80    proptest! {
81        #[test]
82        #[allow(unused_must_use)]
83        fn parse_doesnt_crash(s in "D\\PC*") {
84            DRecord::parse(&s);
85        }
86    }
87}