Add support for converting from/to Url structs (closes: #1)
* Introduce and document the `url` feature * Implement `From<&GeoUri>` and `From<GeoUri>` for `Url` * Implement `TryFrom<&Url>` and `TryFrom<Url>` for `GeoUri` * Add and extend tests
This commit is contained in:
parent
2628e96740
commit
758a3f8072
|
@ -9,9 +9,13 @@ readme = "README.md"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
keywords = ["geolocation", "uri", "parser", "rfc5870"]
|
keywords = ["geolocation", "uri", "parser", "rfc5870"]
|
||||||
|
|
||||||
|
[features]
|
||||||
|
url = ["dep:url"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
derive_builder = "0.11.2"
|
derive_builder = "0.11.2"
|
||||||
thiserror = "1.0.35"
|
thiserror = "1.0.35"
|
||||||
|
url = { version = "2.3.1", optional = true }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
float_eq = "1.0.0"
|
float_eq = "1.0.0"
|
||||||
|
|
29
README.md
29
README.md
|
@ -90,6 +90,35 @@ let geo_uri = GeoUri::try_from((52.107, 5.134)).expect("valid coordinates");
|
||||||
let geo_uri = GeoUri::try_from((52.107, 5.134, 3.6)).expect("valid coordinates");
|
let geo_uri = GeoUri::try_from((52.107, 5.134, 3.6)).expect("valid coordinates");
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Feature: `url`
|
||||||
|
|
||||||
|
You can enable the `url` feature to convert from and to
|
||||||
|
[`Url`](https://docs.rs/url/2/url/struct.Url.html) structs from the
|
||||||
|
[`url`](https://docs.rs/url/2/url) crate.
|
||||||
|
|
||||||
|
Enable the feature in your `Cargo.toml` first:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
geo-uri = { version = "X.Y.Z", features = ["url"] }
|
||||||
|
```
|
||||||
|
|
||||||
|
Then you can do:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
use geo_uri::GeoUri;
|
||||||
|
use url::Url;
|
||||||
|
|
||||||
|
let url = Url::parse("geo:52.107,5.134,3.6").expect("valid URL");
|
||||||
|
let geo_uri = GeoUri::try_from(&url).expect("valid geo URI");
|
||||||
|
let geo_url = Url::from(geo_uri);
|
||||||
|
|
||||||
|
assert_eq!(url, geo_url);
|
||||||
|
```
|
||||||
|
|
||||||
|
Note that it is always possible to transform a [`GeoUri`] into an [`Url`], but
|
||||||
|
not always the other way around! This is because the format of the coordinates
|
||||||
|
and parameters after the URI scheme "geo:" may be invalid!
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
geo-uri-rs is licensed under the MIT license (see the `LICENSE` file or
|
geo-uri-rs is licensed under the MIT license (see the `LICENSE` file or
|
||||||
|
|
76
src/lib.rs
76
src/lib.rs
|
@ -18,6 +18,8 @@
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::num::ParseFloatError;
|
use std::num::ParseFloatError;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
#[cfg(feature = "url")]
|
||||||
|
use url::Url;
|
||||||
|
|
||||||
use derive_builder::Builder;
|
use derive_builder::Builder;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
@ -452,6 +454,20 @@ impl fmt::Display for GeoUri {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "url")]
|
||||||
|
impl From<&GeoUri> for Url {
|
||||||
|
fn from(geo_uri: &GeoUri) -> Self {
|
||||||
|
Url::parse(&geo_uri.to_string()).expect("valid URL")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "url")]
|
||||||
|
impl From<GeoUri> for Url {
|
||||||
|
fn from(geo_uri: GeoUri) -> Self {
|
||||||
|
Url::from(&geo_uri)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl FromStr for GeoUri {
|
impl FromStr for GeoUri {
|
||||||
type Err = Error;
|
type Err = Error;
|
||||||
|
|
||||||
|
@ -499,6 +515,24 @@ impl TryFrom<(f64, f64, f64)> for GeoUri {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "url")]
|
||||||
|
impl TryFrom<&Url> for GeoUri {
|
||||||
|
type Error = Error;
|
||||||
|
|
||||||
|
fn try_from(url: &Url) -> Result<Self, Self::Error> {
|
||||||
|
GeoUri::parse(url.as_str())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "url")]
|
||||||
|
impl TryFrom<Url> for GeoUri {
|
||||||
|
type Error = Error;
|
||||||
|
|
||||||
|
fn try_from(url: Url) -> Result<Self, Self::Error> {
|
||||||
|
GeoUri::try_from(&url)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl PartialEq for GeoUri {
|
impl PartialEq for GeoUri {
|
||||||
fn eq(&self, other: &Self) -> bool {
|
fn eq(&self, other: &Self) -> bool {
|
||||||
// In the WGS-84 CRS the the longitude is ignored for the poles.
|
// In the WGS-84 CRS the the longitude is ignored for the poles.
|
||||||
|
@ -787,6 +821,25 @@ mod tests {
|
||||||
assert_eq!(&geo_uri.to_string(), "geo:52.107,5.134,3.6;u=25000");
|
assert_eq!(&geo_uri.to_string(), "geo:52.107,5.134,3.6;u=25000");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "url")]
|
||||||
|
#[test]
|
||||||
|
fn geo_uri_from() {
|
||||||
|
let geo_uri = GeoUri {
|
||||||
|
crs: CoordRefSystem::Wgs84,
|
||||||
|
latitude: 52.107,
|
||||||
|
longitude: 5.134,
|
||||||
|
altitude: Some(3.6),
|
||||||
|
uncertainty: Some(1000.0),
|
||||||
|
};
|
||||||
|
let url = Url::from(&geo_uri);
|
||||||
|
assert_eq!(url.scheme(), "geo");
|
||||||
|
assert_eq!(url.path(), "52.107,5.134,3.6;u=1000");
|
||||||
|
|
||||||
|
let url = Url::from(geo_uri);
|
||||||
|
assert_eq!(url.scheme(), "geo");
|
||||||
|
assert_eq!(url.path(), "52.107,5.134,3.6;u=1000");
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn geo_uri_from_str() -> Result<(), Error> {
|
fn geo_uri_from_str() -> Result<(), Error> {
|
||||||
let geo_uri = GeoUri::from_str("geo:52.107,5.134")?;
|
let geo_uri = GeoUri::from_str("geo:52.107,5.134")?;
|
||||||
|
@ -800,12 +853,14 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn geo_uri_try_from() -> Result<(), Error> {
|
fn geo_uri_try_from() -> Result<(), Error> {
|
||||||
|
// &str
|
||||||
let geo_uri = GeoUri::try_from("geo:52.107,5.134")?;
|
let geo_uri = GeoUri::try_from("geo:52.107,5.134")?;
|
||||||
assert_float_eq!(geo_uri.latitude, 52.107, abs <= 0.001);
|
assert_float_eq!(geo_uri.latitude, 52.107, abs <= 0.001);
|
||||||
assert_float_eq!(geo_uri.longitude, 5.134, abs <= 0.001);
|
assert_float_eq!(geo_uri.longitude, 5.134, abs <= 0.001);
|
||||||
assert_eq!(geo_uri.altitude, None);
|
assert_eq!(geo_uri.altitude, None);
|
||||||
assert_eq!(geo_uri.uncertainty, None);
|
assert_eq!(geo_uri.uncertainty, None);
|
||||||
|
|
||||||
|
// (f64, f64)
|
||||||
let geo_uri = GeoUri::try_from((51.107, 5.134))?;
|
let geo_uri = GeoUri::try_from((51.107, 5.134))?;
|
||||||
assert_float_eq!(geo_uri.latitude, 51.107, abs <= 0.001);
|
assert_float_eq!(geo_uri.latitude, 51.107, abs <= 0.001);
|
||||||
assert_float_eq!(geo_uri.longitude, 5.134, abs <= 0.001);
|
assert_float_eq!(geo_uri.longitude, 5.134, abs <= 0.001);
|
||||||
|
@ -821,6 +876,7 @@ mod tests {
|
||||||
Err(Error::OutOfRangeLongitude)
|
Err(Error::OutOfRangeLongitude)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// (f64, f64, f64)
|
||||||
let geo_uri = GeoUri::try_from((51.107, 5.134, 3.6))?;
|
let geo_uri = GeoUri::try_from((51.107, 5.134, 3.6))?;
|
||||||
assert_float_eq!(geo_uri.latitude, 51.107, abs <= 0.001);
|
assert_float_eq!(geo_uri.latitude, 51.107, abs <= 0.001);
|
||||||
assert_float_eq!(geo_uri.longitude, 5.134, abs <= 0.001);
|
assert_float_eq!(geo_uri.longitude, 5.134, abs <= 0.001);
|
||||||
|
@ -839,6 +895,26 @@ mod tests {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "url")]
|
||||||
|
#[test]
|
||||||
|
fn geo_uri_try_from_url() -> Result<(), Error> {
|
||||||
|
// Url
|
||||||
|
let url = Url::parse("geo:51.107,5.134,3.6;crs=wgs84;u=1000;foo=bar").expect("valid URL");
|
||||||
|
let geo_uri = GeoUri::try_from(&url)?;
|
||||||
|
assert_float_eq!(geo_uri.latitude, 51.107, abs <= 0.001);
|
||||||
|
assert_float_eq!(geo_uri.longitude, 5.134, abs <= 0.001);
|
||||||
|
assert_float_eq!(geo_uri.altitude.unwrap(), 3.6, abs <= 0.1);
|
||||||
|
assert_eq!(geo_uri.uncertainty, Some(1000.0));
|
||||||
|
|
||||||
|
let geo_uri = GeoUri::try_from(url)?;
|
||||||
|
assert_float_eq!(geo_uri.latitude, 51.107, abs <= 0.001);
|
||||||
|
assert_float_eq!(geo_uri.longitude, 5.134, abs <= 0.001);
|
||||||
|
assert_float_eq!(geo_uri.altitude.unwrap(), 3.6, abs <= 0.1);
|
||||||
|
assert_eq!(geo_uri.uncertainty, Some(1000.0));
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn geo_uri_partial_eq() -> Result<(), GeoUriBuilderError> {
|
fn geo_uri_partial_eq() -> Result<(), GeoUriBuilderError> {
|
||||||
let geo_uri = GeoUri::builder()
|
let geo_uri = GeoUri::builder()
|
||||||
|
|
Loading…
Reference in New Issue