diff --git a/Cargo.toml b/Cargo.toml index 97b9129..788092f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "latlon" -version = "0.1.1" +version = "0.1.2" authors = ["Ondřej Hruška "] description = "Parse latitude/longitude from many common formats" edition = "2018" diff --git a/src/lib.rs b/src/lib.rs index a43cdce..ef28b3c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,7 +1,9 @@ #[macro_use] extern crate lazy_static; -use geo_types::Point; +// re-export Point so `geo_types` do not have to be added as a dependency +// to store the `parse()` function's result. +pub use geo_types::Point; use regex::Regex; use std::convert::TryFrom; diff --git a/src/tests.rs b/src/tests.rs index d57215c..c17ee35 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -17,6 +17,17 @@ fn dms_ns_dms_ew() { assert_eq!(reference, parse(r#"40°26′46N79°58′56W"#).unwrap(), "compact, no sec mark"); assert_eq!(reference, parse(r#"40 26 46 N 79 58 56 W"#).unwrap(), "no symbols"); assert_eq!(reference, parse(r#"-40 26 46 S -79 58 56 E"#).unwrap(), "inverted"); + + assert_eq!(reference, parse(r#"40° 26’ 46″ N 79° 58’ 56″ W"#).unwrap(), "q1"); + assert_eq!(reference, parse(r#"40° 26' 46” N 79° 58' 56” W"#).unwrap(), "q2"); + assert_eq!(reference, parse(r#"40° 26′ 46" N 79° 58′ 56" W"#).unwrap(), "q3"); + assert_eq!(reference, parse(r#"40° 26‘ 46“ N 79° 58‘ 56“ W"#).unwrap(), "q4"); + assert_eq!(reference, parse(r#"40° 26‛ 46″ N 79° 58‛ 56″ W"#).unwrap(), "q5"); + + parse(r#"90° 0′ 0″ N 180° 0′ 0″ E"#).unwrap(); + parse(r#"90° 0′ 0″ S 180° 0′ 0″ W"#).unwrap(); + parse(r#"-90° 0′ 0″ N -180° 0′ 0″ E"#).unwrap(); + parse(r#"-90° 0′ 0″ S -180° 0′ 0″ W"#).unwrap(); } #[test] @@ -35,6 +46,17 @@ fn ns_dms_ew_dms() { assert_eq!(reference, parse(r#"N40°26′46W79°58′56"#).unwrap(), "compact, no sec mark"); assert_eq!(reference, parse(r#"N 40 26 46 W 79 58 56"#).unwrap(), "no symbols"); assert_eq!(reference, parse(r#"S -40 26 46 E -79 58 56"#).unwrap(), "inverted"); + + assert_eq!(reference, parse(r#"N 40° 26’ 46″ W 79° 58’ 56″"#).unwrap(), "q1"); + assert_eq!(reference, parse(r#"N 40° 26' 46” W 79° 58' 56”"#).unwrap(), "q2"); + assert_eq!(reference, parse(r#"N 40° 26′ 46" W 79° 58′ 56""#).unwrap(), "q3"); + assert_eq!(reference, parse(r#"N 40° 26‘ 46“ W 79° 58‘ 56“"#).unwrap(), "q4"); + assert_eq!(reference, parse(r#"N 40° 26‛ 46″ W 79° 58‛ 56″"#).unwrap(), "q5"); + + parse(r#"N 90° 0′ 0″ E 180° 0′ 0″"#).unwrap(); + parse(r#"S 90° 0′ 0″ W 180° 0′ 0″"#).unwrap(); + parse(r#"N -90° 0′ 0″ E -180° 0′ 0″"#).unwrap(); + parse(r#"S -90° 0′ 0″ W -180° 0′ 0″"#).unwrap(); } #[test] @@ -51,6 +73,15 @@ fn dms_dms() { assert_eq!(reference, parse(r#"40° 26′ 46″ ; 79° 58′ 56″"#).unwrap(), "semi3"); assert_eq!(reference, parse(r#"40°26′46″79°58′56″"#).unwrap(), "compact"); assert_eq!(reference, parse(r#"40 26 46 79 58 56"#).unwrap(), "no symbols"); + + assert_eq!(reference, parse(r#"40° 26’ 46″ 79° 58’ 56″"#).unwrap(), "q1"); + assert_eq!(reference, parse(r#"40° 26' 46” 79° 58' 56”"#).unwrap(), "q2"); + assert_eq!(reference, parse(r#"40° 26′ 46" 79° 58′ 56""#).unwrap(), "q3"); + assert_eq!(reference, parse(r#"40° 26‘ 46“ 79° 58‘ 56“"#).unwrap(), "q4"); + assert_eq!(reference, parse(r#"40° 26‛ 46″ 79° 58‛ 56″"#).unwrap(), "q5"); + + parse(r#"90° 0′ 0″ 180° 0′ 0″"#).unwrap(); + parse(r#"-90° 0′ 0″ -180° 0′ 0″"#).unwrap(); } #[test] @@ -73,6 +104,17 @@ fn dm_ns_dm_ew() { assert_eq!(reference, parse(r#"40°26.433N79°58.933W"#).unwrap(), "compact, no min mark"); assert_eq!(reference, parse(r#"40 26.433 N 79 58.933 W"#).unwrap(), "no symbols"); assert_eq!(reference, parse(r#"-40 26.433 S -79 58.933 E"#).unwrap(), "inverted"); + + assert_eq!(reference, parse(r#"40° 26.433’ N 79° 58.933’ W"#).unwrap(), "q1"); + assert_eq!(reference, parse(r#"40° 26.433' N 79° 58.933' W"#).unwrap(), "q2"); + assert_eq!(reference, parse(r#"40° 26.433′ N 79° 58.933′ W"#).unwrap(), "q3"); + assert_eq!(reference, parse(r#"40° 26.433‘ N 79° 58.933‘ W"#).unwrap(), "q4"); + assert_eq!(reference, parse(r#"40° 26.433‛ N 79° 58.933‛ W"#).unwrap(), "q5"); + + parse(r#"90° 0′ N 180° 0′ E"#).unwrap(); + parse(r#"90° 0′ S 180° 0′ W"#).unwrap(); + parse(r#"-90° 0′ N -180° 0′ E"#).unwrap(); + parse(r#"-90° 0′ S -180° 0′ W"#).unwrap(); } #[test] @@ -95,6 +137,17 @@ fn ns_dm_ew_dm() { assert_eq!(reference, parse(r#"N40°26.433W79°58.933"#).unwrap(), "compact, no min mark"); assert_eq!(reference, parse(r#"N40 26.433W79 58.933"#).unwrap(), "no symbols"); assert_eq!(reference, parse(r#"S -40 26.433 E -79 58.933"#).unwrap(), "inverted"); + + assert_eq!(reference, parse(r#"N 40° 26.433’ W 79° 58.933’"#).unwrap(), "q1"); + assert_eq!(reference, parse(r#"N 40° 26.433' W 79° 58.933'"#).unwrap(), "q2"); + assert_eq!(reference, parse(r#"N 40° 26.433′ W 79° 58.933′"#).unwrap(), "q3"); + assert_eq!(reference, parse(r#"N 40° 26.433‘ W 79° 58.933‘"#).unwrap(), "q4"); + assert_eq!(reference, parse(r#"N 40° 26.433‛ W 79° 58.933‛"#).unwrap(), "q5"); + + parse(r#"N 90° 0′ E 180° 0′"#).unwrap(); + parse(r#"S 90° 0′ W 180° 0′"#).unwrap(); + parse(r#"N -90° 0′ E -180° 0′"#).unwrap(); + parse(r#"S -90° 0′ W -180° 0′"#).unwrap(); } #[test] @@ -115,6 +168,15 @@ fn dm_dm() { assert_eq!(reference, parse(r#"40° 26.433′ ; 79° 58.933′"#).unwrap(), "semi4"); assert_eq!(reference, parse(r#"40°26.433′79°58.933′"#).unwrap(), "compact"); assert_eq!(reference, parse(r#"40 26.433 79 58.933"#).unwrap(), "no symbols"); + + assert_eq!(reference, parse(r#"40° 26.433’ 79° 58.933’"#).unwrap(), "q1"); + assert_eq!(reference, parse(r#"40° 26.433' 79° 58.933'"#).unwrap(), "q2"); + assert_eq!(reference, parse(r#"40° 26.433′ 79° 58.933′"#).unwrap(), "q3"); + assert_eq!(reference, parse(r#"40° 26.433‘ 79° 58.933‘"#).unwrap(), "q4"); + assert_eq!(reference, parse(r#"40° 26.433‛ 79° 58.933‛"#).unwrap(), "q5"); + + parse(r#"90° 0′ 180° 0′"#).unwrap(); + parse(r#"-90° 0′ -180° 0′"#).unwrap(); } #[test] @@ -133,6 +195,11 @@ fn d_ns_d_ew() { assert_eq!(reference, parse(r#"40.44055° N ;79.9822° W"#).unwrap(), "semi3"); assert_eq!(reference, parse(r#"40.44055N79.9822W"#).unwrap(), "compact"); assert_eq!(reference, parse(r#"-40.44055° S -79.9822° E"#).unwrap(), "inverted"); + + parse(r#"90° N 180° E"#).unwrap(); + parse(r#"90° S 180° W"#).unwrap(); + parse(r#"-90° N -180° E"#).unwrap(); + parse(r#"-90° S -180° W"#).unwrap(); } #[test] @@ -149,6 +216,11 @@ fn d_d() { assert_eq!(reference, parse(r#"40.44055°;79.9822°"#).unwrap(), "semi2"); assert_eq!(reference, parse(r#"40.44055° ,79.9822°"#).unwrap(), "comma3"); assert_eq!(reference, parse(r#"40.44055° ;79.9822°"#).unwrap(), "semi3"); + + parse(r#"90 180"#).unwrap(); + parse(r#"-90 -180"#).unwrap(); + parse(r#"90° 180°"#).unwrap(); + parse(r#"-90° -180°"#).unwrap(); } @@ -171,6 +243,17 @@ fn dms_nsew() { assert_eq!(reference, parse_lng(r#"40°26′46E"#).unwrap(), "compact, no sec mark"); assert_eq!(reference, parse_lng(r#"40 26 46 E"#).unwrap(), "no symbols"); assert_eq!(reference, parse_lng(r#"-40 26 46 W"#).unwrap(), "inverted"); + + assert_eq!(reference, parse_lng(r#"40° 26’ 46″ E"#).unwrap(), "q1"); + assert_eq!(reference, parse_lng(r#"40° 26' 46” E"#).unwrap(), "q2"); + assert_eq!(reference, parse_lng(r#"40° 26′ 46" E"#).unwrap(), "q3"); + assert_eq!(reference, parse_lng(r#"40° 26‘ 46“ E"#).unwrap(), "q4"); + assert_eq!(reference, parse_lng(r#"40° 26‛ 46″ E"#).unwrap(), "q5"); + + parse_lat(r#"90° 0′ 0″ N"#).unwrap(); + parse_lat(r#"90° 0′ 0″ S"#).unwrap(); + parse_lng(r#"180° 0′ 0″ E"#).unwrap(); + parse_lng(r#"180° 0′ 0″ W"#).unwrap(); } #[test] @@ -188,6 +271,17 @@ fn nsew_dms() { assert_eq!(reference, parse_lng(r#"E40°26′46"#).unwrap(), "compact, no sec mark"); assert_eq!(reference, parse_lng(r#"E 40 26 46"#).unwrap(), "no symbols"); assert_eq!(reference, parse_lng(r#"W -40 26 46"#).unwrap(), "inverted"); + + assert_eq!(reference, parse_lng(r#"E 40° 26’ 46″"#).unwrap(), "q1"); + assert_eq!(reference, parse_lng(r#"E 40° 26' 46”"#).unwrap(), "q2"); + assert_eq!(reference, parse_lng(r#"E 40° 26′ 46""#).unwrap(), "q3"); + assert_eq!(reference, parse_lng(r#"E 40° 26‘ 46“"#).unwrap(), "q4"); + assert_eq!(reference, parse_lng(r#"E 40° 26‛ 46″"#).unwrap(), "q5"); + + parse_lat(r#"N 90° 0′ 0″"#).unwrap(); + parse_lat(r#"S 90° 0′ 0″"#).unwrap(); + parse_lng(r#"E 180° 0′ 0″"#).unwrap(); + parse_lng(r#"W 180° 0′ 0″"#).unwrap(); } #[test] @@ -211,11 +305,16 @@ fn dms() { // ’'′‘‛ // ″”"“ - assert_eq!(reference, parse_lng(r#"40° 26’ 46″"#).unwrap(), "normal"); - assert_eq!(reference, parse_lng(r#"40° 26' 46”"#).unwrap(), "normal"); - assert_eq!(reference, parse_lng(r#"40° 26′ 46""#).unwrap(), "normal"); - assert_eq!(reference, parse_lng(r#"40° 26‘ 46“"#).unwrap(), "normal"); - assert_eq!(reference, parse_lng(r#"40° 26‛ 46″"#).unwrap(), "normal"); + assert_eq!(reference, parse_lng(r#"40° 26’ 46″"#).unwrap(), "q1"); + assert_eq!(reference, parse_lng(r#"40° 26' 46”"#).unwrap(), "q2"); + assert_eq!(reference, parse_lng(r#"40° 26′ 46""#).unwrap(), "q3"); + assert_eq!(reference, parse_lng(r#"40° 26‘ 46“"#).unwrap(), "q4"); + assert_eq!(reference, parse_lng(r#"40° 26‛ 46″"#).unwrap(), "q5"); + + parse_lat(r#"90° 0’ 0″"#).unwrap(); + parse_lat(r#"-90° 0’ 0″"#).unwrap(); + parse_lng(r#"180° 0’ 0″"#).unwrap(); + parse_lng(r#"-180° 0’ 0″"#).unwrap(); } #[test] @@ -237,6 +336,17 @@ fn dm_nsew() { assert_eq!(reference, parse_lng(r#"40°26.433E"#).unwrap(), "compact, no min mark"); assert_eq!(reference, parse_lng(r#"40 26.433 E"#).unwrap(), "no symbols"); assert_eq!(reference, parse_lng(r#"-40 26.433 W"#).unwrap(), "inverted"); + + assert_eq!(reference, parse_lng(r#"40° 26.433’ E"#).unwrap(), "q1"); + assert_eq!(reference, parse_lng(r#"40° 26.433' E"#).unwrap(), "q2"); + assert_eq!(reference, parse_lng(r#"40° 26.433′ E"#).unwrap(), "q3"); + assert_eq!(reference, parse_lng(r#"40° 26.433‘ E"#).unwrap(), "q4"); + assert_eq!(reference, parse_lng(r#"40° 26.433‛ E"#).unwrap(), "q5"); + + parse_lat(r#"90° 0′ N"#).unwrap(); + parse_lat(r#"90° 0′ S"#).unwrap(); + parse_lng(r#"180° 0′ E"#).unwrap(); + parse_lng(r#"180° 0′ W"#).unwrap(); } #[test] @@ -258,6 +368,24 @@ fn nsew_dm() { assert_eq!(reference, parse_lng(r#"E40°26.433"#).unwrap(), "compact, no min mark"); assert_eq!(reference, parse_lng(r#"E40 26.433"#).unwrap(), "no symbols"); assert_eq!(reference, parse_lng(r#"W -40 26.433"#).unwrap(), "inverted"); + + // quotes + assert_eq!(reference, parse_lng(r#"E 40° 26.433’"#).unwrap(), "q1"); + assert_eq!(reference, parse_lng(r#"E 40° 26.433'"#).unwrap(), "q2"); + assert_eq!(reference, parse_lng(r#"E 40° 26.433′"#).unwrap(), "q3"); + assert_eq!(reference, parse_lng(r#"E 40° 26.433‘"#).unwrap(), "q4"); + assert_eq!(reference, parse_lng(r#"E 40° 26.433‛"#).unwrap(), "q5"); + + + // verify corner cases don't error + parse_lat(r#"N 90° 0.0′"#).unwrap(); + parse_lat(r#"N -90° 0′"#).unwrap(); + parse_lat(r#"S 90° 0′"#).unwrap(); + parse_lat(r#"S -90° 0′"#).unwrap(); + + parse_lng(r#"E -180° 0′"#).unwrap(); + parse_lng(r#"W 180° 0′"#).unwrap(); + parse_lng(r#"W -180° 0′"#).unwrap(); } #[test] @@ -278,6 +406,17 @@ fn dm() { assert_eq!(reference, parse_lng(r#"40°26.433′"#).unwrap(), "compact"); assert_eq!(reference, parse_lng(r#"40 26.433"#).unwrap(), "no symbols"); assert_eq!(ref_neg, parse_lng(r#"-40° 26.433′"#).unwrap(), "neg"); + + // verify corner cases don't error + parse_lat(r#"0° 0′"#).unwrap(); + parse_lat(r#"0° 0"#).unwrap(); + parse_lat(r#"90° 0"#).unwrap(); + parse_lat(r#"-90° 0"#).unwrap(); + + parse_lng(r#"0° 0′"#).unwrap(); + parse_lng(r#"180° 0′"#).unwrap(); + parse_lng(r#"-180° 0′"#).unwrap(); + parse_lng(r#"-180° 0.000′"#).unwrap(); } #[test] @@ -294,6 +433,17 @@ fn d_nsew() { assert_eq!(reference, parse_lng(r#"40.44055 E"#).unwrap(), "no deg"); assert_eq!(reference, parse_lng(r#"40.44055E"#).unwrap(), "compact"); assert_eq!(reference, parse_lng(r#"-40.44055° W"#).unwrap(), "inverted"); + + // verify corner cases don't error + parse_lat(r#"1.123456789° N"#).unwrap(); + parse_lat(r#"90° S"#).unwrap(); + parse_lat(r#"-90°S"#).unwrap(); + parse_lat(r#"1°S"#).unwrap(); + + parse_lng(r#"1.123456789°E"#).unwrap(); + parse_lng(r#"180.0000°W"#).unwrap(); + parse_lng(r#"-180 E"#).unwrap(); + parse_lng(r#"1W"#).unwrap(); } #[test] @@ -310,4 +460,15 @@ fn d() { assert_eq!(reference, parse_lng(r#"40,44055°"#).unwrap(), "comma dec"); assert_eq!(reference, parse_lng(r#"40.44055"#).unwrap(), "no deg"); assert_eq!(ref_neg, parse_lng(r#"-40.44055"#).unwrap(), "no deg"); + + // verify corner cases don't error + parse_lat(r#"1.123456789°"#).unwrap(); + parse_lat(r#"90°"#).unwrap(); + parse_lat(r#"-90°"#).unwrap(); + parse_lat(r#"1°"#).unwrap(); + + parse_lng(r#"1.123456789°"#).unwrap(); + parse_lng(r#"180.0000°"#).unwrap(); + parse_lng(r#"-180°"#).unwrap(); + parse_lng(r#"1°"#).unwrap(); }