use crate::{Alphanumeric, Error};
pub type Latitude<'a> = Alphanumeric<'a, 9>;
impl<'a> Latitude<'a> {
pub fn as_decimal(&self) -> Result<f64, Error> {
let hem = self.first();
let deg = parse_numeric!(2, u8, &self.0[1..3])? as f64;
let min = parse_numeric!(2, u8, &self.0[3..5])? as f64;
let sec = parse_numeric!(4, u32, &self.0[5..9])? as f64 / 100.0;
let decimal = deg + min / 60.0 + sec / 3600.0;
match hem {
b'N' => Ok(decimal),
b'S' => Ok(-decimal),
_ => Err(Error::InvalidCharacter {
field: "Latitude",
byte: hem,
expected: "N or S",
}),
}
}
}
pub type Longitude<'a> = Alphanumeric<'a, 10>;
impl<'a> Longitude<'a> {
pub fn as_decimal(&self) -> Result<f64, Error> {
let hem = self.first();
let deg = parse_numeric!(3, u8, &self.0[1..4])? as f64;
let min = parse_numeric!(2, u8, &self.0[4..6])? as f64;
let sec = parse_numeric!(4, u32, &self.0[6..10])? as f64 / 100.0;
let decimal = deg + min / 60.0 + sec / 3600.0;
match hem {
b'E' => Ok(decimal),
b'W' => Ok(-decimal),
_ => Err(Error::InvalidCharacter {
field: "Longitude",
byte: hem,
expected: "E or W",
}),
}
}
}
#[cfg(test)]
mod tests {
use crate::FixedField;
use super::*;
#[test]
fn parses_latitude() {
let lat = Latitude::from_bytes(b"N40394857").expect("latitude should parse");
assert_eq!(lat.as_decimal(), Ok(40.663491666666665));
}
#[test]
fn parses_longitude() {
let long = Longitude::from_bytes(b"W0741444230").expect("longitude should parse");
assert_eq!(long.as_decimal(), Ok(-74.24561944444444));
}
}