nmea_kit/nmea/sentences/
dse.rs1use crate::nmea::field::{FieldReader, FieldWriter, NmeaEncodable};
2
3#[derive(Debug, Clone, PartialEq)]
5pub struct DseDataSet {
6 pub code: Option<String>,
8 pub data: Option<String>,
10}
11
12#[derive(Debug, Clone, PartialEq)]
18pub struct Dse {
19 pub total: Option<u8>,
21 pub number: Option<u8>,
23 pub ack: Option<char>,
25 pub mmsi: Option<String>,
27 pub datasets: Vec<DseDataSet>,
29}
30
31impl Dse {
32 pub fn parse(fields: &[&str]) -> Option<Self> {
35 let mut r = FieldReader::new(fields);
36 let total = r.u8();
37 let number = r.u8();
38 let ack = r.char();
39 let mmsi = r.string();
40 let mut datasets = Vec::new();
41 loop {
42 let code = r.string();
43 if code.is_none() {
44 break;
45 }
46 datasets.push(DseDataSet {
47 code,
48 data: r.string(),
49 });
50 }
51 Some(Self {
52 total,
53 number,
54 ack,
55 mmsi,
56 datasets,
57 })
58 }
59}
60
61impl NmeaEncodable for Dse {
62 const SENTENCE_TYPE: &str = "DSE";
63
64 fn encode(&self) -> Result<Vec<String>, crate::EncodeError> {
65 let mut w = FieldWriter::new();
66 w.u8(self.total);
67 w.u8(self.number);
68 w.char(self.ack);
69 w.string(self.mmsi.as_deref());
70 for ds in &self.datasets {
71 w.string(ds.code.as_deref());
72 w.string(ds.data.as_deref());
73 }
74 w.finish()
75 }
76}
77
78#[cfg(test)]
79mod tests {
80 use super::*;
81 use crate::parse_frame;
82
83 #[test]
84 fn dse_empty() {
85 let s = Dse {
86 total: None,
87 number: None,
88 ack: None,
89 mmsi: None,
90 datasets: vec![],
91 }
92 .to_sentence("CD")
93 .expect("encode");
94 let f = parse_frame(s.trim()).expect("valid");
95 let d = Dse::parse(&f.fields).expect("parse");
96 assert!(d.total.is_none());
97 assert!(d.mmsi.is_none());
98 assert!(d.datasets.is_empty());
99 }
100
101 #[test]
102 fn dse_encode_roundtrip() {
103 let original = Dse {
104 total: Some(1),
105 number: Some(1),
106 ack: Some('A'),
107 mmsi: Some("3380400790".to_string()),
108 datasets: vec![DseDataSet {
109 code: Some("00".to_string()),
110 data: Some("46504437".to_string()),
111 }],
112 };
113 let sentence = original.to_sentence("CD").expect("encode");
114 let frame = parse_frame(sentence.trim()).expect("re-parse");
115 let parsed = Dse::parse(&frame.fields).expect("parse");
116 assert_eq!(original, parsed);
117 }
118
119 #[test]
120 fn dse_cddse_gonmea() {
121 let f = parse_frame("$CDDSE,1,1,A,3380400790,00,46504437*15").expect("valid DSE");
122 let d = Dse::parse(&f.fields).expect("parse DSE");
123 assert_eq!(d.total, Some(1));
124 assert_eq!(d.number, Some(1));
125 assert_eq!(d.ack, Some('A'));
126 assert_eq!(d.mmsi, Some("3380400790".to_string()));
127 assert_eq!(d.datasets.len(), 1);
128 assert_eq!(d.datasets[0].code, Some("00".to_string()));
129 assert_eq!(d.datasets[0].data, Some("46504437".to_string()));
130 }
131
132 #[test]
133 fn dse_multiple_datasets_gonmea() {
134 let f =
135 parse_frame("$CDDSE,1,1,A,3380400790,00,46504437,01,16501437*17").expect("valid DSE");
136 let d = Dse::parse(&f.fields).expect("parse DSE");
137 assert_eq!(d.mmsi, Some("3380400790".to_string()));
138 assert_eq!(d.datasets.len(), 2);
139 assert_eq!(d.datasets[0].code, Some("00".to_string()));
140 assert_eq!(d.datasets[0].data, Some("46504437".to_string()));
141 assert_eq!(d.datasets[1].code, Some("01".to_string()));
142 assert_eq!(d.datasets[1].data, Some("16501437".to_string()));
143 }
144}