use crate::nmea::field::{FieldReader, FieldWriter};
#[derive(Debug, Clone, PartialEq)]
pub struct Rot {
pub rate_of_turn: Option<f32>,
pub valid: Option<char>,
}
impl Rot {
pub const SENTENCE_TYPE: &str = "ROT";
pub fn parse(fields: &[&str]) -> Option<Self> {
let mut r = FieldReader::new(fields);
Some(Self {
rate_of_turn: r.f32(),
valid: r.char(),
})
}
pub fn encode(&self) -> Vec<String> {
let mut w = FieldWriter::new();
w.f32(self.rate_of_turn);
w.char(self.valid);
w.finish()
}
pub fn to_sentence(&self, talker: &str) -> String {
let fields = self.encode();
let field_refs: Vec<&str> = fields.iter().map(|s| s.as_str()).collect();
crate::encode_frame('$', talker, Self::SENTENCE_TYPE, &field_refs)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::parse_frame;
#[test]
fn rot_empty() {
let f = parse_frame("$IIROT,,*49").expect("valid");
let r = Rot::parse(&f.fields).expect("parse");
assert!(r.rate_of_turn.is_none());
assert!(r.valid.is_none());
}
#[test]
fn rot_encode_roundtrip() {
let rot = Rot {
rate_of_turn: Some(35.6),
valid: Some('A'),
};
let sentence = rot.to_sentence("GP");
assert!(sentence.starts_with("$GPROT,"));
let frame = parse_frame(sentence.trim()).expect("re-parse");
let rot2 = Rot::parse(&frame.fields).expect("re-parse ROT");
assert_eq!(rot.rate_of_turn, rot2.rate_of_turn);
assert_eq!(rot.valid, rot2.valid);
}
#[test]
fn rot_negative_pynmeagps() {
let frame = parse_frame("$IIROT,-7.3,A*0F").expect("valid");
let rot = Rot::parse(&frame.fields).expect("parse ROT");
assert!((rot.rate_of_turn.expect("rot") - (-7.3)).abs() < 0.1);
assert_eq!(rot.valid, Some('A'));
}
#[test]
fn rot_positive_gpsd() {
let frame = parse_frame("$GPROT,35.6,A*01").expect("valid");
let rot = Rot::parse(&frame.fields).expect("parse ROT");
assert!((rot.rate_of_turn.expect("rot") - 35.6).abs() < 0.1);
assert_eq!(rot.valid, Some('A'));
}
#[test]
fn rot_zero_gpsd() {
let frame = parse_frame("$HEROT,0.0,A*2B").expect("valid");
let rot = Rot::parse(&frame.fields).expect("parse ROT");
assert!((rot.rate_of_turn.expect("rot") - 0.0).abs() < 0.01);
assert_eq!(rot.valid, Some('A'));
}
}