Start work on generating urls
This commit is contained in:
parent
432f7259ac
commit
773063daf0
61
Cargo.lock
generated
61
Cargo.lock
generated
@ -350,6 +350,15 @@ version = "1.0.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
||||
|
||||
[[package]]
|
||||
name = "form_urlencoded"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8"
|
||||
dependencies = [
|
||||
"percent-encoding",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures"
|
||||
version = "0.3.27"
|
||||
@ -577,6 +586,16 @@ dependencies = [
|
||||
"want",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "idna"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6"
|
||||
dependencies = [
|
||||
"unicode-bidi",
|
||||
"unicode-normalization",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "1.9.2"
|
||||
@ -1354,6 +1373,7 @@ dependencies = [
|
||||
"nom",
|
||||
"pluscodes",
|
||||
"thiserror",
|
||||
"url",
|
||||
"utm",
|
||||
]
|
||||
|
||||
@ -1512,6 +1532,21 @@ dependencies = [
|
||||
"time-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tinyvec"
|
||||
version = "1.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50"
|
||||
dependencies = [
|
||||
"tinyvec_macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tinyvec_macros"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
|
||||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.26.0"
|
||||
@ -1702,12 +1737,27 @@ dependencies = [
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-bidi"
|
||||
version = "0.3.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-normalization"
|
||||
version = "0.1.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921"
|
||||
dependencies = [
|
||||
"tinyvec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-segmentation"
|
||||
version = "1.10.1"
|
||||
@ -1726,6 +1776,17 @@ version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
|
||||
|
||||
[[package]]
|
||||
name = "url"
|
||||
version = "2.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643"
|
||||
dependencies = [
|
||||
"form_urlencoded",
|
||||
"idna",
|
||||
"percent-encoding",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "utm"
|
||||
version = "0.1.6"
|
||||
|
@ -22,3 +22,4 @@ nom = "7.1.3"
|
||||
pluscodes = "0.5.0"
|
||||
utm = "0.1.6"
|
||||
thiserror = "1.0.38"
|
||||
url = "2.3.1"
|
||||
|
@ -21,6 +21,13 @@ pub enum Error {
|
||||
NomErr(String),
|
||||
#[error("No UTM zone letter")]
|
||||
NoUtmZoneLetter,
|
||||
/// The url could not be parsed at all
|
||||
#[error("Could not parse URL: {0}")]
|
||||
UrlParseError(url::ParseError),
|
||||
|
||||
/// A latitude/longitude could not be extracted from the url
|
||||
#[error("Could not find lat/lon in URL: {0}")]
|
||||
NoUrlLatLon(String),
|
||||
}
|
||||
|
||||
impl From<pluscodes::Error> for Error {
|
||||
@ -35,6 +42,12 @@ impl From<utm::WSG84ToLatLonError> for Error {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<url::ParseError> for Error {
|
||||
fn from(e: url::ParseError) -> Self {
|
||||
Self::UrlParseError(e)
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: std::fmt::Debug> From<nom::Err<E>> for Error {
|
||||
fn from(e: nom::Err<E>) -> Self {
|
||||
Self::NomErr(format!("{e:?}"))
|
||||
|
@ -1,6 +1,16 @@
|
||||
use std::fmt;
|
||||
|
||||
use crate::Error;
|
||||
use nom::{
|
||||
character::complete::space0,
|
||||
combinator::{eof, map_res},
|
||||
sequence::tuple,
|
||||
IResult,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
common::{optional_separator, parse_f64},
|
||||
Error,
|
||||
};
|
||||
|
||||
#[derive(PartialEq, Debug, Clone, Copy)]
|
||||
pub struct LatLon {
|
||||
@ -26,6 +36,23 @@ impl LatLon {
|
||||
pub fn get_lon(&self) -> f64 {
|
||||
self.lon
|
||||
}
|
||||
|
||||
/// Parse a latitude and longitude as two floating point numbers separated by a comma and/or whitespace only (no bearings)
|
||||
/// Parse only the entire string
|
||||
pub fn parse_full(i: &str) -> IResult<&str, Self> {
|
||||
map_res(
|
||||
tuple((
|
||||
space0,
|
||||
parse_f64,
|
||||
optional_separator(','),
|
||||
space0,
|
||||
parse_f64,
|
||||
space0,
|
||||
eof,
|
||||
)),
|
||||
|(_, lat, _, _, lon, _, _)| Self::new(lat, lon),
|
||||
)(i)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for LatLon {
|
||||
|
@ -6,6 +6,7 @@ pub mod dmm;
|
||||
pub mod dms;
|
||||
pub mod latlon;
|
||||
pub mod plus;
|
||||
pub mod urls;
|
||||
pub mod utm;
|
||||
pub use error::Error;
|
||||
// pub mod xpin;
|
||||
|
72
spatial-coordinate-systems/src/urls.rs
Normal file
72
spatial-coordinate-systems/src/urls.rs
Normal file
@ -0,0 +1,72 @@
|
||||
use crate::{Error, LatLon};
|
||||
use std::str::FromStr;
|
||||
use url::Url;
|
||||
|
||||
#[derive(PartialEq, Debug, Clone)]
|
||||
pub struct CoordinateUrls {
|
||||
google_maps: String,
|
||||
latlon: LatLon,
|
||||
}
|
||||
|
||||
impl CoordinateUrls {
|
||||
pub fn parse(i: &str) -> Result<Self, Error> {
|
||||
let url = Url::parse(i.trim())?;
|
||||
|
||||
// Try to parse a url from google maps
|
||||
url.query_pairs()
|
||||
.find_map(|(key, value)| {
|
||||
if key != "query" {
|
||||
return None;
|
||||
}
|
||||
|
||||
LatLon::parse_full(value.as_ref())
|
||||
.map(|(_, ret)| ret)
|
||||
.ok()
|
||||
.map(Self::try_from)
|
||||
})
|
||||
.ok_or_else(|| Error::NoUrlLatLon(i.to_string()))?
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&CoordinateUrls> for LatLon {
|
||||
fn from(coordinate: &CoordinateUrls) -> LatLon {
|
||||
coordinate.latlon
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<LatLon> for CoordinateUrls {
|
||||
type Error = Error;
|
||||
|
||||
fn try_from(latlon: LatLon) -> Result<Self, Self::Error> {
|
||||
let latlon_str = format!("{},{}", latlon.get_lat(), latlon.get_lon());
|
||||
|
||||
Ok(Self {
|
||||
google_maps: String::from(Url::parse_with_params(
|
||||
"https://www.google.com/maps/search/",
|
||||
&[("api", "1"), ("query", &latlon_str)],
|
||||
)?),
|
||||
latlon,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for CoordinateUrls {
|
||||
type Err = Error;
|
||||
|
||||
fn from_str(i: &str) -> Result<Self, Self::Err> {
|
||||
Self::parse(i).map_err(Into::into)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_general() {
|
||||
assert!(dbg!(CoordinateUrls::parse(
|
||||
"https://www.google.com/maps/search/?query=27,23"
|
||||
))
|
||||
.is_ok());
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user