fix unicode quotes fuckup

master
Ondřej Hruška 4 years ago
parent e2de07f86e
commit e420705b12
Signed by: MightyPork
GPG Key ID: 2C5FD5035250423D
  1. 2
      Cargo.toml
  2. 10
      README.md
  3. 138
      src/lib.rs
  4. 10
      src/tests.rs

@ -1,6 +1,6 @@
[package]
name = "latlon"
version = "0.1.0"
version = "0.1.1"
authors = ["Ondřej Hruška <ondra@ondrovo.com>"]
description = "Parse latitude/longitude from many common formats"
edition = "2018"

@ -22,10 +22,10 @@ let lng : f64 = latlon::parse_lng("E 14°26.94732'").unwrap();
Example of supported formats:
- `40° 26′ 46″ N 79° 58′ 56″ W`
- `N 40° 26′ 46″ W 79° 58′ 56″`
- `40° 26' 46" N 79° 58' 56" W`
- `N 40° 26' 46" W 79° 58' 56"`
- `40° 26.767' N 79° 58.933' W`
- `40° 26′ 46″ 79° 58′ 56″`, `40° 26′ 46″, 79° 58′ 56″`, ...
- `40° 26' 46" 79° 58' 56"`, `40° 26' 46", 79° 58' 56"`, ...
- `N 40° 26.767' W 79° 58.933'`
- `40° 26.767' 79° 58.933'`, `40° 26.767', 79° 58.933'`, ...
- `N 40.446° W 79.982°`
@ -37,7 +37,7 @@ Example of supported formats:
- Whitespace is optional and ignored, except for formats that would become unparsable.
- Degree, minute and second symbols can be omitted.
- Comma (`,`) may be used as an alternate decimal separator.
- Unicode quotes (`’`, `”`) may be used in place of apostrophe and double quote (`'`, `"`)
- Unicode quotes (e.g. `’`, `”`) are supported
for minutes and seconds.
- The two coordinates can be separated by comma (`,`), semicolon (`;`), whitespace (` `), or nothing
- The two coordinates can be separated by comma (`,`), semicolon (`;`), whitespace, or nothing
at all, if not ambiguous.

@ -18,98 +18,98 @@ use crate::errors::ParseErrorInternal;
// Two-sided patterns
lazy_static! {
// 40° 26′ 46″ N 79° 58′ 56″ W
static ref RE_DMS_NS_DMS_EW: Regex = Regex::new(r"(?x)
static ref RE_DMS_NS_DMS_EW: Regex = Regex::new(r#"(?x)
^
(-?\d{1,2})(?:°\s*|\s+)
(\d{1,2})(?:[]\s*|\s+)
(\d{1,2}(?:[.,]\d+)?)[]?\s*
(\d{1,2})(?:[']\s*|\s+)
(\d{1,2}(?:[.,]\d+)?)["]?\s*
(N|S)
\s*
[,;]?
\s*
(-?\d{1,3})(?:°\s*|\s+)
(\d{1,2})(?:[]\s*|\s+)
(\d{1,2}(?:[.,]\d+)?)[]?\s*
(\d{1,2})(?:[']\s*|\s+)
(\d{1,2}(?:[.,]\d+)?)["]?\s*
(E|W)
$
").unwrap();
"#).unwrap();
// N 40° 26′ 46″ W 79° 58′ 56″
static ref RE_NS_DMS_EW_DMS: Regex = Regex::new(r"(?x)
static ref RE_NS_DMS_EW_DMS: Regex = Regex::new(r#"(?x)
^
(N|S)\s*
(-?\d{1,2})(?:°\s*|\s+)
(\d{1,2})(?:[]\s*|\s+)
(\d{1,2}(?:[.,]\d+)?)[]?
(\d{1,2})(?:[']\s*|\s+)
(\d{1,2}(?:[.,]\d+)?)["]?
\s*
[,;]?
\s*
(E|W)\s*
(-?\d{1,3})(?:°\s*|\s+)
(\d{1,2})(?:[]\s*|\s+)
(\d{1,2}(?:[.,]\d+)?)[]?
(\d{1,2})(?:[']\s*|\s+)
(\d{1,2}(?:[.,]\d+)?)["]?
$
").unwrap();
"#).unwrap();
// 40° 26′ 46″ 79° 58′ 56″
static ref RE_DMS_DMS: Regex = Regex::new(r"(?x)
static ref RE_DMS_DMS: Regex = Regex::new(r#"(?x)
^
(-?\d{1,2})(?:°\s*|\s+)
(\d{1,2})(?:[]\s*|\s+)
(\d{1,2}(?:[.,]\d+)?)[]?\s*
(\d{1,2})(?:[']\s*|\s+)
(\d{1,2}(?:[.,]\d+)?)["]?\s*
[,;]?
\s*
(-?\d{1,3})(?:°\s*|\s+)
(\d{1,2})(?:[]\s*|\s+)
(\d{1,2}(?:[.,]\d+)?)[]?
(\d{1,2})(?:[']\s*|\s+)
(\d{1,2}(?:[.,]\d+)?)["]?
$
").unwrap();
"#).unwrap();
// 40° 26.767' N 79° 58.933' W
static ref RE_DM_NS_DM_EW: Regex = Regex::new(r"(?x)
static ref RE_DM_NS_DM_EW: Regex = Regex::new(r#"(?x)
^
(-?\d{1,2})(?:°\s*|\s+)
(\d{1,2}(?:[.,]\d+)?)[]?\s*
(\d{1,2}(?:[.,]\d+)?)[']?\s*
(N|S)
\s*
[,;]?
\s*
(-?\d{1,3})(?:°\s*|\s+)
(\d{1,2}(?:[.,]\d+)?)[]?\s*
(\d{1,2}(?:[.,]\d+)?)[']?\s*
(E|W)
$
").unwrap();
"#).unwrap();
// N 40° 26.767' W 79° 58.933'
static ref RE_NS_DM_EW_DM: Regex = Regex::new(r"(?x)
static ref RE_NS_DM_EW_DM: Regex = Regex::new(r#"(?x)
^
(N|S)\s*
(-?\d{1,2})(?:°\s*|\s+)
(\d{1,2}(?:[.,]\d+)?)[]?
(\d{1,2}(?:[.,]\d+)?)[']?
\s*
[,;]?
\s*
(E|W)\s*
(-?\d{1,3})(?:°\s*|\s+)
(\d{1,2}(?:[.,]\d+)?)[]?
(\d{1,2}(?:[.,]\d+)?)[']?
$
").unwrap();
"#).unwrap();
// 40° 26.767' 79° 58.933'
static ref RE_DM_DM: Regex = Regex::new(r"(?x)
static ref RE_DM_DM: Regex = Regex::new(r#"(?x)
^
(-?\d{1,2})(?:°\s*|\s+)
(\d{1,2}(?:[.,]\d+)?)[]?
(\d{1,2}(?:[.,]\d+)?)[']?
\s*
[,;]?
\s*
(-?\d{1,3})(?:°\s*|\s+)
(\d{1,2}(?:[.,]\d+)?)[]?
(\d{1,2}(?:[.,]\d+)?)[']?
$
").unwrap();
"#).unwrap();
// N 40.446° W 79.982°
static ref RE_NS_D_EW_D: Regex = Regex::new(r"(?x)
static ref RE_NS_D_EW_D: Regex = Regex::new(r#"(?x)
^
(N|S)\s*
(-?\d{1,2}(?:[.,]\d+)?)°?
@ -119,10 +119,10 @@ lazy_static! {
(E|W)\s*
(-?\d{1,3}(?:[.,]\d+)?)°?
$
").unwrap();
"#).unwrap();
// 40.446° N 79.982° W
static ref RE_D_NS_D_EW: Regex = Regex::new(r"(?x)
static ref RE_D_NS_D_EW: Regex = Regex::new(r#"(?x)
^
(-?\d{1,2}(?:[.,]\d+)?)°?\s*
(N|S)\s*
@ -131,96 +131,96 @@ lazy_static! {
(-?\d{1,3}(?:[.,]\d+)?)°?\s*
(E|W)
$
").unwrap();
"#).unwrap();
// 40.446° 79.982°
static ref RE_D_D: Regex = Regex::new(r"(?x)
static ref RE_D_D: Regex = Regex::new(r#"(?x)
^
(-?\d{1,2}(?:[.,]\d+)?)(?:°\s*[,;]?\s*|\s*[,;]\s*|\s+)
(-?\d{1,3}(?:[.,]\d+)?)°?
$
").unwrap();
"#).unwrap();
}
// One-sided patterns
lazy_static! {
// 40° 26′ 46″ N
static ref RE_DMS_NSEW: Regex = Regex::new(r"(?x)
static ref RE_DMS_NSEW: Regex = Regex::new(r#"(?x)
^
(-?\d{1,3})(?:°\s*|\s+)
(\d{1,2})(?:[]\s*|\s+)
(\d{1,2}(?:[.,]\d+)?)[]?\s*
(\d{1,2})(?:[']\s*|\s+)
(\d{1,2}(?:[.,]\d+)?)["]?\s*
(N|S|E|W)
$
").unwrap();
"#).unwrap();
// N 40° 26′ 46″
static ref RE_NSEW_DMS: Regex = Regex::new(r"(?x)
static ref RE_NSEW_DMS: Regex = Regex::new(r#"(?x)
^
(N|S|E|W)\s*
(-?\d{1,3})(?:°\s*|\s+)
(\d{1,2})(?:[]\s*|\s+)
(\d{1,2}(?:[.,]\d+)?)[]?
(\d{1,2})(?:[']\s*|\s+)
(\d{1,2}(?:[.,]\d+)?)["]?
$
").unwrap();
"#).unwrap();
// 40° 26′ 46″
static ref RE_DMS: Regex = Regex::new(r"(?x)
static ref RE_DMS: Regex = Regex::new(r#"(?x)
^
(-?\d{1,3})(?:°\s*|\s+)
(\d{1,2})(?:[]\s*|\s+)
(\d{1,2}(?:[.,]\d+)?)[]?\s*
(\d{1,2})(?:[']\s*|\s+)
(\d{1,2}(?:[.,]\d+)?)["]?\s*
$
").unwrap();
"#).unwrap();
// 40° 26.767' N
static ref RE_DM_NSEW: Regex = Regex::new(r"(?x)
static ref RE_DM_NSEW: Regex = Regex::new(r#"(?x)
^
(-?\d{1,2})(?:°\s*|\s+)
(\d{1,2}(?:[.,]\d+)?)[]?\s*
(-?\d{1,3})(?:°\s*|\s+)
(\d{1,2}(?:[.,]\d+)?)[']?\s*
(N|S|E|W)
$
").unwrap();
"#).unwrap();
// N 40° 26.767'
static ref RE_NSEW_DM: Regex = Regex::new(r"(?x)
static ref RE_NSEW_DM: Regex = Regex::new(r#"(?x)
^
(N|S|E|W)\s*
(-?\d{1,2})(?:°\s*|\s+)
(\d{1,2}(?:[.,]\d+)?)[]?
(-?\d{1,3})(?:°\s*|\s+)
(\d{1,2}(?:[.,]\d+)?)[']?
$
").unwrap();
"#).unwrap();
// 40° 26.767'
static ref RE_DM: Regex = Regex::new(r"(?x)
static ref RE_DM: Regex = Regex::new(r#"(?x)
^
(-?\d{1,2})(?:°\s*|\s+)
(\d{1,2}(?:[.,]\d+)?)[]?
(-?\d{1,3})(?:°\s*|\s+)
(\d{1,2}(?:[.,]\d+)?)[']?
$
").unwrap();
"#).unwrap();
// N 40.446°
static ref RE_NSEW_D: Regex = Regex::new(r"(?x)
static ref RE_NSEW_D: Regex = Regex::new(r#"(?x)
^
(N|S|E|W)\s*
(-?\d{1,2}(?:[.,]\d+)?)°?
(-?\d{1,3}(?:[.,]\d+)?)°?
$
").unwrap();
"#).unwrap();
// 40.446° N
static ref RE_D_NSEW: Regex = Regex::new(r"(?x)
static ref RE_D_NSEW: Regex = Regex::new(r#"(?x)
^
(-?\d{1,2}(?:[.,]\d+)?)°?\s*
(-?\d{1,3}(?:[.,]\d+)?)°?\s*
(N|S|E|W)
$
").unwrap();
"#).unwrap();
// 40.446°
static ref RE_D: Regex = Regex::new(r"(?x)
static ref RE_D: Regex = Regex::new(r#"(?x)
^
(-?\d{1,2}(?:[.,]\d+)?)°?
(-?\d{1,3}(?:[.,]\d+)?)°?
$
").unwrap();
"#).unwrap();
}
/// Parsed degrees, minutes, seconds

@ -206,6 +206,16 @@ fn dms() {
assert_eq!(reference, parse_lng(r#"40°26′46″"#).unwrap(), "compact");
assert_eq!(reference, parse_lng(r#"40 26 46"#).unwrap(), "no symbols");
assert_eq!(ref_neg, parse_lng(r#"-40° 26′ 46″"#).unwrap(), "neg");
// Test all the weird quotation marks
// ’'′‘‛
// ″”"“
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");
}
#[test]

Loading…
Cancel
Save