diff --git a/spatial-coordinate-systems/src/lib.rs b/spatial-coordinate-systems/src/lib.rs index 8d45335..7a8f1ad 100644 --- a/spatial-coordinate-systems/src/lib.rs +++ b/spatial-coordinate-systems/src/lib.rs @@ -35,6 +35,7 @@ impl Direction { } } +#[derive(Debug, PartialEq)] pub enum Coordinate { DD(dd::Coordinate), DMS(dms::Coordinate), @@ -63,11 +64,11 @@ impl Coordinate { } } -impl TryInto for Coordinate { +impl TryFrom for LatLon { type Error = (); - fn try_into(self) -> Result { - match self { + fn try_from(value: Coordinate) -> Result { + match value { Coordinate::DD(dd) => dd.try_into().or(Err(())), Coordinate::DMM(dm) => dm.try_into(), Coordinate::DMS(dms) => dms.try_into(), @@ -103,6 +104,31 @@ impl From for Coordinate { } } +impl TryFrom for dms::Coordinate { + type Error = (); + fn try_from(c: Coordinate) -> Result { + dms::Coordinate::try_from(LatLon::try_from(c)?) + } +} +impl TryFrom for dmm::Coordinate { + type Error = (); + fn try_from(c: Coordinate) -> Result { + dmm::Coordinate::try_from(LatLon::try_from(c)?).or(Err(())) + } +} +impl TryFrom for utm::Coordinate { + type Error = (); + fn try_from(c: Coordinate) -> Result { + utm::Coordinate::try_from(LatLon::try_from(c)?) + } +} +impl TryFrom for plus::Coordinate { + type Error = (); + fn try_from(c: Coordinate) -> Result { + plus::Coordinate::try_from(LatLon::try_from(c)?).or(Err(())) + } +} + impl FromStr for Coordinate { type Err = (); @@ -110,3 +136,39 @@ impl FromStr for Coordinate { Self::parse(i).map_err(|_| ()).map(|(_, ret)| ret) } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_general() { + assert_eq!( + Coordinate::from_str("0.000000 100.500278"), + Ok(Coordinate::DD(dd::Coordinate { + lat: 0.0, + lon: 100.500278 + })) + ); + + assert_eq!( + Coordinate::from_str("47N 666962.588 0.000"), + Ok(Coordinate::UTM(utm::Coordinate { + zone_num: 47, + zone_letter: 'N', + easting: 666962.588, + northing: 0.0 + })) + ); + + assert_eq!( + dms::Coordinate::try_from(Coordinate::from_str("0.000000 100.500278").unwrap()), + dms::Coordinate::try_from(Coordinate::from_str("0.000000 100.500278").unwrap()) + ) + + // assert_eq!( + // LatLon::try_from(Coordinate::from_str("0.000000 100.500278").unwrap()), + // LatLon::try_from(Coordinate::from_str("47N 666962.588 0.000").unwrap()) + // ) + } +} diff --git a/spatial-coordinate-systems/src/utm.rs b/spatial-coordinate-systems/src/utm.rs index 88b861a..9f75865 100644 --- a/spatial-coordinate-systems/src/utm.rs +++ b/spatial-coordinate-systems/src/utm.rs @@ -1,16 +1,16 @@ use crate::{ - common::{parse_direction, parse_f64}, LatLon, + common::{parse_direction, parse_f64}, + LatLon, }; use nom::{ - bytes::complete::{take}, + bytes::complete::take, character::complete::{self, space0, space1}, combinator::{map_opt, opt}, - sequence::{tuple}, + sequence::tuple, IResult, }; use std::str::FromStr; - #[derive(PartialEq, Debug)] pub struct Coordinate { pub zone_num: u8, @@ -27,7 +27,7 @@ impl Coordinate { /// assert!(Coordinate::parse("10S 706832mE 4344683N").is_ok()); /// assert!(Coordinate::parse("10S 706832E 4344683N").is_ok()); /// assert!(Coordinate::parse("10S706832mE 4344683mN").is_err()); - /// assert!(Coordinate::parse("10S 706832mE 4344683m").is_err()); + /// assert!(Coordinate::parse("10S 706832mE 4344683m").is_ok()); /// ``` pub fn parse(i: &str) -> IResult<&str, Self> { map_opt( @@ -39,11 +39,12 @@ impl Coordinate { parse_f64, // TODO: Can there be spaces around the m here or no? opt(complete::char('m')), - parse_direction, + // TODO: Should I allow a direction here nor no + opt(parse_direction), space1, parse_f64, opt(complete::char('m')), - parse_direction, + opt(parse_direction), )), |( zone_num,