fix unicode quotes fuckup
This commit is contained in:
+1
-1
@@ -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.
|
||||
|
||||
+69
-69
@@ -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]
|
||||
|
||||
Reference in New Issue
Block a user