diff --git a/spatial-coordinate-systems/src/dd.rs b/spatial-coordinate-systems/src/dd.rs index 970e94d..a3ee078 100644 --- a/spatial-coordinate-systems/src/dd.rs +++ b/spatial-coordinate-systems/src/dd.rs @@ -16,7 +16,7 @@ use std::str::FromStr; pub struct Coordinate(pub f64, pub f64); impl Coordinate { - pub fn parse(i: &str) -> IResult<&str, Coordinate> { + pub fn parse(i: &str) -> IResult<&str, Self> { map_opt( tuple((double, optional_separator(','), double)), |(ns, _, ew)| { @@ -30,3 +30,11 @@ impl Coordinate { )(i) } } + +impl FromStr for Coordinate { + type Err = (); + + fn from_str(i: &str) -> Result { + Self::parse(i).map_err(|_| ()).map(|(_, ret)| ret) + } +} diff --git a/spatial-coordinate-systems/src/dmm.rs b/spatial-coordinate-systems/src/dmm.rs index 4488c3d..1ef6ab8 100644 --- a/spatial-coordinate-systems/src/dmm.rs +++ b/spatial-coordinate-systems/src/dmm.rs @@ -15,7 +15,7 @@ use std::str::FromStr; #[derive(PartialEq, Debug)] pub struct Coordinate(pub DMM, pub DMM); impl Coordinate { - pub fn parse(i: &str) -> IResult<&str, Coordinate> { + pub fn parse(i: &str) -> IResult<&str, Self> { map_opt( tuple((DMM::parse, optional_separator(','), DMM::parse)), |(ns, _, ew)| { @@ -30,6 +30,14 @@ impl Coordinate { } } +impl FromStr for Coordinate { + type Err = (); + + fn from_str(i: &str) -> Result { + Self::parse(i).map_err(|_| ()).map(|(_, ret)| ret) + } +} + #[derive(PartialEq, Debug)] pub struct DMM { pub degrees: i16, diff --git a/spatial-coordinate-systems/src/dms.rs b/spatial-coordinate-systems/src/dms.rs index 54dc049..74eb139 100644 --- a/spatial-coordinate-systems/src/dms.rs +++ b/spatial-coordinate-systems/src/dms.rs @@ -16,7 +16,7 @@ use std::str::FromStr; pub struct Coordinate(pub DMS, pub DMS); impl Coordinate { - pub fn parse(i: &str) -> IResult<&str, Coordinate> { + pub fn parse(i: &str) -> IResult<&str, Self> { map_opt( tuple((DMS::parse, optional_separator(','), DMS::parse)), |(ns, _, ew)| { @@ -31,6 +31,14 @@ impl Coordinate { } } +impl FromStr for Coordinate { + type Err = (); + + fn from_str(i: &str) -> Result { + Self::parse(i).map_err(|_| ()).map(|(_, ret)| ret) + } +} + #[derive(PartialEq, Debug)] pub struct DMS { pub degrees: i16, @@ -64,6 +72,7 @@ impl DMS { )(i) } } + impl FromStr for DMS { type Err = (); diff --git a/spatial-coordinate-systems/src/lib.rs b/spatial-coordinate-systems/src/lib.rs index 4789549..9d5954f 100644 --- a/spatial-coordinate-systems/src/lib.rs +++ b/spatial-coordinate-systems/src/lib.rs @@ -5,6 +5,7 @@ mod common; pub mod dd; pub mod dmm; pub mod dms; +pub mod plus; use dmm::DMM; use dms::DMS; @@ -50,8 +51,28 @@ pub enum Coordinate { DD(dd::Coordinate), DMS(dms::Coordinate), DM(dmm::Coordinate), - // UTM(utm::UTMCoordinate), - // Plus(plus::PlusCoordinate), + // UTM(utm::Coordinate), + Plus(plus::Coordinate), +} + +impl Coordinate { + pub fn parse(i: &str) -> IResult<&str, Self> { + map( + tuple(( + space0, + alt(( + map(dd::Coordinate::parse, Coordinate::DD), + map(dms::Coordinate::parse, Coordinate::DMS), + map(dmm::Coordinate::parse, Coordinate::DM), + // map(utm::Coordinate::parse, Coordinate::UTM), + map(plus::Coordinate::parse, Coordinate::Plus), + )), + space0, + eof, + )), + |(_, coordinate, _, _)| coordinate, + )(i) + } } pub enum CoordinateSystem { @@ -62,19 +83,6 @@ impl FromStr for Coordinate { type Err = (); fn from_str(i: &str) -> Result { - tuple(( - space0, - alt(( - map(dd::Coordinate::parse, Coordinate::DD), - map(dms::Coordinate::parse, Coordinate::DMS), - map(dmm::Coordinate::parse, Coordinate::DM), - // map(utm::parse_coordinate, Coordinate::UTM), - // map(plus::parse_coordinate, Coordinate::PLUS), - )), - space0, - eof, - ))(i) - .map(|(_, (_, coordinate, _, _))| coordinate) - .map_err(|_| ()) + Self::parse(i).map_err(|_| ()).map(|(_, ret)| ret) } } diff --git a/spatial-coordinate-systems/src/plus.rs b/spatial-coordinate-systems/src/plus.rs new file mode 100644 index 0000000..5389536 --- /dev/null +++ b/spatial-coordinate-systems/src/plus.rs @@ -0,0 +1,44 @@ +use crate::{ + common::{optional_separator, parse_direction}, + Direction, +}; +use nom::{ + branch::alt, + bytes::complete::take_while, + character::complete::{self, space0, space1}, + combinator::{eof, map, map_opt, map_res, opt}, + number::complete::double, + sequence::{pair, tuple}, + IResult, +}; +use std::str::FromStr; + +const PLUSCODE_CHARS: [char; 22] = [ + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'C', 'F', 'G', 'H', 'J', 'M', 'P', 'Q', 'R', + 'V', 'W', 'X', +]; + +#[derive(PartialEq, Debug)] +pub struct Coordinate(pub f64, pub f64); + +impl Coordinate { + pub fn parse(i: &str) -> IResult<&str, Self> { + map_opt(pluscode_chars, |c| { + pluscodes::decode(c) + .map(|coord| Coordinate(coord.latitude, coord.longitude)) + .ok() + })(i) + } +} + +impl FromStr for Coordinate { + type Err = (); + + fn from_str(i: &str) -> Result { + Self::parse(i).map_err(|_| ()).map(|(_, ret)| ret) + } +} + +fn pluscode_chars(i: &str) -> IResult<&str, &str> { + take_while(|c| PLUSCODE_CHARS.contains(&c))(i) +}