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"
|
||||
keywords = ["geolocation", "uri", "parser", "rfc5870"]
|
||||
|
||||
[features]
|
||||
url = ["dep:url"]
|
||||
|
||||
[dependencies]
|
||||
derive_builder = "0.11.2"
|
||||
thiserror = "1.0.35"
|
||||
url = { version = "2.3.1", optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
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");
|
||||
```
|
||||
|
||||
### 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
|
||||
|
||||
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::num::ParseFloatError;
|
||||
use std::str::FromStr;
|
||||
#[cfg(feature = "url")]
|
||||
use url::Url;
|
||||
|
||||
use derive_builder::Builder;
|
||||
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 {
|
||||
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 {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
// 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");
|
||||
}
|
||||
|
||||
#[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]
|
||||
fn geo_uri_from_str() -> Result<(), Error> {
|
||||
let geo_uri = GeoUri::from_str("geo:52.107,5.134")?;
|
||||
|
@ -800,12 +853,14 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn geo_uri_try_from() -> Result<(), Error> {
|
||||
// &str
|
||||
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.longitude, 5.134, abs <= 0.001);
|
||||
assert_eq!(geo_uri.altitude, None);
|
||||
assert_eq!(geo_uri.uncertainty, None);
|
||||
|
||||
// (f64, f64)
|
||||
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.longitude, 5.134, abs <= 0.001);
|
||||
|
@ -821,6 +876,7 @@ mod tests {
|
|||
Err(Error::OutOfRangeLongitude)
|
||||
);
|
||||
|
||||
// (f64, f64, f64)
|
||||
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.longitude, 5.134, abs <= 0.001);
|
||||
|
@ -839,6 +895,26 @@ mod tests {
|
|||
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]
|
||||
fn geo_uri_partial_eq() -> Result<(), GeoUriBuilderError> {
|
||||
let geo_uri = GeoUri::builder()
|
||||
|
|
Loading…
Reference in New Issue