nmea_kit/nmea/sentences/
tlb.rs1use crate::nmea::field::{FieldReader, FieldWriter, NmeaEncodable};
2
3#[derive(Debug, Clone, PartialEq)]
5pub struct TlbTarget {
6 pub number: Option<u8>,
8 pub label: Option<String>,
10}
11
12#[derive(Debug, Clone, PartialEq)]
16pub struct Tlb {
17 pub targets: Vec<TlbTarget>,
19}
20
21impl Tlb {
22 pub fn parse(fields: &[&str]) -> Option<Self> {
25 let mut r = FieldReader::new(fields);
26 let mut targets = Vec::new();
27 loop {
28 let number = r.u8();
29 if number.is_none() {
30 break;
31 }
32 targets.push(TlbTarget {
33 number,
34 label: r.string(),
35 });
36 }
37 Some(Self { targets })
38 }
39}
40
41impl NmeaEncodable for Tlb {
42 const SENTENCE_TYPE: &str = "TLB";
43
44 fn encode(&self) -> Result<Vec<String>, crate::EncodeError> {
45 let mut w = FieldWriter::new();
46 for t in &self.targets {
47 w.u8(t.number);
48 w.string(t.label.as_deref());
49 }
50 w.finish()
51 }
52}
53
54#[cfg(test)]
55mod tests {
56 use super::*;
57 use crate::parse_frame;
58
59 #[test]
60 fn tlb_empty() {
61 let s = Tlb { targets: vec![] }.to_sentence("RA").expect("encode");
62 let f = parse_frame(s.trim()).expect("valid");
63 let t = Tlb::parse(&f.fields).expect("parse");
64 assert!(t.targets.is_empty());
65 }
66
67 #[test]
68 fn tlb_encode_roundtrip() {
69 let original = Tlb {
70 targets: vec![
71 TlbTarget {
72 number: Some(1),
73 label: Some("ALPHA".to_string()),
74 },
75 TlbTarget {
76 number: Some(2),
77 label: Some("BETA".to_string()),
78 },
79 ],
80 };
81 let sentence = original.to_sentence("RA").expect("encode");
82 let frame = parse_frame(sentence.trim()).expect("re-parse");
83 let parsed = Tlb::parse(&frame.fields).expect("parse");
84 assert_eq!(original, parsed);
85 }
86
87 #[test]
88 fn tlb_ratlb_gonmea() {
89 let f = parse_frame("$RATLB,1,XXX*20").expect("valid TLB");
90 let t = Tlb::parse(&f.fields).expect("parse TLB");
91 assert_eq!(t.targets.len(), 1);
92 assert_eq!(t.targets[0].number, Some(1));
93 assert_eq!(t.targets[0].label, Some("XXX".to_string()));
94 }
95}