use std::rc::Rc;
use crate::records::util::{Coordinate, Time};
use crate::error::IGCError::FixInitError;
use crate::{Result, StrWrapper};
#[cfg(feature = "serde")] use serde::{Deserialize, Serialize};
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[derive(Debug, Clone, PartialEq)]
pub struct Fix {
pub timestamp: Time,
pub coordinates: Coordinate,
pub pressure_alt: i16,
pub gps_alt: Option<i16>, pub extension: StrWrapper,
}
impl Fix {
pub(crate) fn parse(line: &str) -> Result<Self> {
if line.chars().count() < 35 {
return Err(FixInitError(format!("\"{}\" is too short to be parsed as a fix", line)))
}
if !line.starts_with('B') {
return Err(FixInitError(format!("\"{}\" does not start with B and can therefore not be parsed as a B record (Fix)", line)))
}
let timestamp = Time::parse(&line[1..7])?;
let coordinates = Coordinate::parse(&line[7..24])?;
let gps_alt = match &line[24..25] {
"A" => match line[30..35].parse::<i16>() {
Ok(alt) => Some(alt),
Err(_) => return Err(FixInitError(format!("\"{}\" could not parse GPS altitude", line)))
},
"V" => None,
_ => return Err(FixInitError(format!("\"{}\" does not have A or V in GPS validity field", line)))
};
let pressure_alt = match line[25..30].parse::<i16>() {
Ok(alt) => alt,
Err(_) => return Err(FixInitError(format!("\"{}\" could not parse pressure altitude", line)))
};
let extension = line[35..].to_string().into();
Ok(
Fix {
timestamp,
coordinates,
pressure_alt,
gps_alt,
extension,
}
)
}
}
#[cfg(test)]
mod tests {
use crate::records::Record;
use crate::records::util::{Latitude, Longitude};
use super::*;
#[test]
fn fix_parsed_correctly() {
let line = "B0941395152202N00032723WA001140015000854106968064092190039002770100";
let record = Record::parse(line).unwrap();
if let Record::B(fix) = record {
let Fix {
timestamp,
coordinates,
pressure_alt,
gps_alt,
extension
} = fix;
let true_coordinate = Coordinate {latitude: Latitude {
degrees: 51, minutes: 52.202, is_north: true
}, longitude: Longitude {
degrees: 0,
minutes: 32.723,
is_east: false,
}};
assert_eq!(Time::from_hms(9, 41, 39).unwrap(), timestamp);
assert_eq!(true_coordinate, coordinates);
assert_eq!(pressure_alt, 114);
assert_eq!(gps_alt, Some(150));
assert_eq!(extension, String::from("00854106968064092190039002770100").into());
} else {
assert!(false)
}
}
#[test]
fn fix_too_short() {
assert!(Fix::parse("B0941395152202N00032723WA001140015").is_err())
}
#[test]
fn negative() {
let line = "A0941395152202N00032723WA001140015000854106968064092190039002770100";
assert!(Fix::parse(line).is_err());
let line = "B0941395152202N00032723WA0A1140015000854106968064092190039002770100";
assert!(Fix::parse(line).is_err());
let line = "B0941395152202N00032723WA011140A15000854106968064092190039002770100";
assert!(Fix::parse(line).is_err());
let line = "B0941395152202N00032723WV001140015000854106968064092190039002770100";
assert!(Fix::parse(line).is_ok());
let line = "B0941395152202N00032723WB001140015000854106968064092190039002770100";
assert!(Fix::parse(line).is_err());
}
}