2022-09-27 17:58:48 +02:00
|
|
|
#![doc = include_str!("../README.md")]
|
2022-09-27 18:01:26 +02:00
|
|
|
#![warn(
|
|
|
|
clippy::all,
|
|
|
|
missing_copy_implementations,
|
|
|
|
missing_debug_implementations,
|
|
|
|
rust_2018_idioms,
|
|
|
|
rustdoc::broken_intra_doc_links,
|
2022-09-29 19:39:13 +02:00
|
|
|
trivial_casts,
|
|
|
|
trivial_numeric_casts,
|
|
|
|
renamed_and_removed_lints,
|
|
|
|
unsafe_code,
|
|
|
|
unstable_features,
|
|
|
|
unused_import_braces,
|
|
|
|
unused_qualifications
|
2022-09-27 18:01:26 +02:00
|
|
|
)]
|
|
|
|
#![deny(missing_docs)]
|
2022-09-27 17:10:45 +02:00
|
|
|
|
|
|
|
use std::fmt;
|
2022-09-29 22:15:28 +02:00
|
|
|
use std::num::ParseFloatError;
|
2022-09-27 17:10:45 +02:00
|
|
|
use std::str::FromStr;
|
|
|
|
|
|
|
|
use derive_builder::Builder;
|
|
|
|
use thiserror::Error;
|
|
|
|
|
|
|
|
/// The scheme name of a geo URI.
|
|
|
|
const URI_SCHEME_NAME: &str = "geo";
|
|
|
|
|
2022-09-29 20:56:48 +02:00
|
|
|
/// Possible geo URI errors.
|
|
|
|
#[derive(Debug, Error, Eq, PartialEq)]
|
|
|
|
pub enum Error {
|
|
|
|
/// The geo URI contains an unparsable/invalid coordinate.
|
|
|
|
#[error("Invalid coordinate in geo URI: {0}")]
|
|
|
|
InvalidCoord(ParseFloatError),
|
|
|
|
|
|
|
|
/// The geo URI contains an unsupported/invalid coordinate reference system.
|
|
|
|
#[error("Invalid coordinate reference system")]
|
|
|
|
InvalidCoordRefSystem,
|
|
|
|
|
2022-09-29 22:15:28 +02:00
|
|
|
/// The geo URI contains an unparsable/invalid uncertainty distance.
|
2022-09-29 20:56:48 +02:00
|
|
|
#[error("Invalid distance in geo URI: {0}")]
|
2022-09-29 22:15:28 +02:00
|
|
|
InvalidUncertainty(ParseFloatError),
|
2022-09-29 20:56:48 +02:00
|
|
|
|
|
|
|
/// The geo URI contains no coordinates.
|
|
|
|
#[error("Missing coordinates in geo URI")]
|
|
|
|
MissingCoords,
|
|
|
|
|
|
|
|
/// The geo URI lacks the latitude coordinate.
|
|
|
|
#[error("Missing latitude coordinate in geo URI")]
|
|
|
|
MissingLatitude,
|
|
|
|
|
|
|
|
/// The geo URI lacks the longitude coordinate.
|
|
|
|
#[error("Missing longitude coordinate in geo URI")]
|
|
|
|
MissingLongitude,
|
|
|
|
|
|
|
|
/// The geo URI is missing a proper scheme, i.e. the prefix `geo:`.
|
|
|
|
#[error("Missing geo URI scheme")]
|
|
|
|
MissingScheme,
|
|
|
|
|
|
|
|
/// The latitude coordinate is out of range of `-90.0..=90.0` degrees.
|
|
|
|
///
|
|
|
|
/// This can only fail for the WGS-84 coordinate reference system.
|
|
|
|
#[error("Latitude coordinate is out of range")]
|
|
|
|
OutOfRangeLatitude,
|
|
|
|
|
2022-09-29 22:15:28 +02:00
|
|
|
/// The longitude coordinate is out of range of `-180.0..=180.0` degrees.
|
2022-09-29 20:56:48 +02:00
|
|
|
///
|
|
|
|
/// This can only fail for the WGS-84 coordinate reference system.
|
|
|
|
#[error("Longitude coordinate is out of range")]
|
|
|
|
OutOfRangeLongitude,
|
2022-09-29 22:15:28 +02:00
|
|
|
|
|
|
|
/// The uncertainty distance is not positive.
|
|
|
|
#[error("Uncertainty distance not positive")]
|
|
|
|
OutOfRangeUncertainty,
|
2022-09-29 20:56:48 +02:00
|
|
|
}
|
|
|
|
|
2022-09-27 17:10:45 +02:00
|
|
|
/// The reference system of the provided coordinates.
|
|
|
|
///
|
|
|
|
/// Currently only the `WGS-84` coordinate reference system is supported.
|
|
|
|
/// It defines the latitude and longitude of the [`GeoUri`] to be in decimal degrees and the
|
|
|
|
/// altitude in meters.
|
|
|
|
///
|
|
|
|
/// For more details see the
|
|
|
|
/// [component description](ttps://www.rfc-editor.org/rfc/rfc5870#section-3.4.2) in
|
|
|
|
/// [RFC 5870](https://www.rfc-editor.org/rfc/rfc5870).
|
|
|
|
#[non_exhaustive]
|
|
|
|
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
2022-09-29 20:51:30 +02:00
|
|
|
pub enum CoordRefSystem {
|
2022-09-27 17:10:45 +02:00
|
|
|
/// The WGS-84 coordinate reference system.
|
|
|
|
Wgs84,
|
|
|
|
}
|
|
|
|
|
2022-09-29 20:51:30 +02:00
|
|
|
impl CoordRefSystem {
|
|
|
|
/// Validates geo location coordinates against the selected coordinate reference system.
|
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```rust
|
2022-09-29 20:56:48 +02:00
|
|
|
/// # use geo_uri::{CoordRefSystem, Error};
|
2022-09-29 20:51:30 +02:00
|
|
|
/// let crs = CoordRefSystem::Wgs84;
|
|
|
|
/// assert_eq!(crs.validate(52.107, 5.134), Ok(()));
|
|
|
|
/// assert_eq!(
|
|
|
|
/// crs.validate(100.0, 5.134), // Latitude not in range `-90.0..=90.0`!
|
2022-09-29 20:56:48 +02:00
|
|
|
/// Err(Error::OutOfRangeLatitude)
|
2022-09-29 20:51:30 +02:00
|
|
|
/// );
|
|
|
|
/// assert_eq!(
|
|
|
|
/// crs.validate(51.107, -200.0), // Longitude not in range `-180.0..=180.0`!
|
2022-09-29 20:56:48 +02:00
|
|
|
/// Err(Error::OutOfRangeLongitude)
|
2022-09-29 20:51:30 +02:00
|
|
|
/// );
|
|
|
|
/// ```
|
2022-09-29 20:56:48 +02:00
|
|
|
pub fn validate(&self, latitude: f64, longitude: f64) -> Result<(), Error> {
|
2022-09-29 20:51:30 +02:00
|
|
|
// This holds only for WGS-84, but it is the only one supported right now!
|
|
|
|
if !(-90.0..=90.0).contains(&latitude) {
|
2022-09-29 20:56:48 +02:00
|
|
|
return Err(Error::OutOfRangeLatitude);
|
2022-09-29 20:51:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// This holds only for WGS-84, but it is the only one supported right now!
|
|
|
|
if !(-180.0..=180.0).contains(&longitude) {
|
2022-09-29 20:56:48 +02:00
|
|
|
return Err(Error::OutOfRangeLongitude);
|
2022-09-29 20:51:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Default for CoordRefSystem {
|
2022-09-27 17:10:45 +02:00
|
|
|
fn default() -> Self {
|
|
|
|
Self::Wgs84
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// A uniform resource identifier for geographic locations (geo URI).
|
|
|
|
///
|
2022-09-29 19:52:49 +02:00
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ## Parsing
|
|
|
|
///
|
|
|
|
/// You can get a [`GeoUri`] by converting it from a geo URI string ([`&str`]):
|
|
|
|
///
|
|
|
|
/// ```rust
|
|
|
|
/// use geo_uri::GeoUri;
|
|
|
|
///
|
2022-09-29 21:25:01 +02:00
|
|
|
/// let geo_uri = GeoUri::try_from("geo:52.107,5.134,3.6;u=1000").expect("valid geo URI");
|
|
|
|
/// assert_eq!(geo_uri.latitude(), 52.107);
|
|
|
|
/// assert_eq!(geo_uri.longitude(), 5.134);
|
|
|
|
/// assert_eq!(geo_uri.altitude(), Some(3.6));
|
2022-09-29 22:15:28 +02:00
|
|
|
/// assert_eq!(geo_uri.uncertainty(), Some(1000.0));
|
2022-09-29 19:52:49 +02:00
|
|
|
/// ```
|
|
|
|
///
|
|
|
|
/// or by using the [`TryFrom`] trait:
|
|
|
|
/// ```
|
|
|
|
/// use geo_uri::GeoUri;
|
|
|
|
/// use std::str::FromStr;
|
|
|
|
///
|
2022-09-29 22:15:28 +02:00
|
|
|
/// let geo_uri = GeoUri::from_str("geo:52.107,5.134;u=2000.0").expect("valid geo URI");
|
2022-09-29 21:25:01 +02:00
|
|
|
/// assert_eq!(geo_uri.latitude(), 52.107);
|
|
|
|
/// assert_eq!(geo_uri.longitude(), 5.134);
|
|
|
|
/// assert_eq!(geo_uri.altitude(), None);
|
2022-09-29 22:15:28 +02:00
|
|
|
/// assert_eq!(geo_uri.uncertainty(), Some(2000.0));
|
2022-09-29 19:52:49 +02:00
|
|
|
/// ```
|
|
|
|
///
|
|
|
|
/// It is also possible to call the parse function directly:
|
|
|
|
///
|
|
|
|
/// ```rust
|
|
|
|
/// use geo_uri::GeoUri;
|
|
|
|
///
|
2022-09-29 21:25:01 +02:00
|
|
|
/// let geo_uri = GeoUri::parse("geo:52.107,5.134,3.6").expect("valid geo URI");
|
|
|
|
/// assert_eq!(geo_uri.latitude(), 52.107);
|
|
|
|
/// assert_eq!(geo_uri.longitude(), 5.134);
|
|
|
|
/// assert_eq!(geo_uri.altitude(), Some(3.6));
|
|
|
|
/// assert_eq!(geo_uri.uncertainty(), None);
|
2022-09-29 19:52:49 +02:00
|
|
|
/// ```
|
|
|
|
///
|
|
|
|
/// ## Generating
|
|
|
|
///
|
|
|
|
/// To get an geo URI string from some coordinates, use the [`GeoUriBuilder`]:
|
|
|
|
///
|
|
|
|
/// ```rust
|
|
|
|
/// use geo_uri::GeoUri;
|
|
|
|
///
|
|
|
|
/// let geo_uri = GeoUri::builder()
|
2022-09-29 21:25:01 +02:00
|
|
|
/// .latitude(52.107)
|
|
|
|
/// .longitude(5.134)
|
2022-09-29 22:15:28 +02:00
|
|
|
/// .uncertainty(1_000.0)
|
2022-09-29 21:25:01 +02:00
|
|
|
/// .build()
|
|
|
|
/// .unwrap();
|
2022-09-29 19:52:49 +02:00
|
|
|
/// assert_eq!(
|
|
|
|
/// geo_uri.to_string(),
|
|
|
|
/// String::from("geo:52.107,5.134;u=1000")
|
|
|
|
/// );
|
|
|
|
/// assert_eq!(
|
|
|
|
/// format!("{geo_uri}"),
|
|
|
|
/// String::from("geo:52.107,5.134;u=1000")
|
|
|
|
/// );
|
|
|
|
/// ```
|
2022-09-27 17:10:45 +02:00
|
|
|
///
|
|
|
|
/// # See also
|
|
|
|
///
|
|
|
|
/// For the proposed IEEE standard, see [RFC 5870](https://www.rfc-editor.org/rfc/rfc5870).
|
|
|
|
#[derive(Builder, Copy, Clone, Debug, Default)]
|
2022-09-29 20:51:30 +02:00
|
|
|
#[builder(build_fn(validate = "Self::validate"))]
|
2022-09-27 17:10:45 +02:00
|
|
|
pub struct GeoUri {
|
|
|
|
/// The coordinate reference system used by the coordinates of this URI.
|
2022-09-29 19:53:07 +02:00
|
|
|
#[builder(default)]
|
2022-09-29 21:25:01 +02:00
|
|
|
crs: CoordRefSystem,
|
|
|
|
|
2022-09-27 17:10:45 +02:00
|
|
|
/// The latitude coordinate of a location.
|
2022-09-29 20:51:30 +02:00
|
|
|
///
|
|
|
|
/// For the WGS-84 coordinate reference system, this should be in the range of
|
|
|
|
/// `-90.0` up until including `90.0` degrees.
|
2022-09-29 21:25:01 +02:00
|
|
|
latitude: f64,
|
|
|
|
|
2022-09-27 17:10:45 +02:00
|
|
|
/// The longitude coordinate of a location.
|
2022-09-29 20:51:30 +02:00
|
|
|
///
|
|
|
|
/// For the WGS-84 coordinate reference system, this should be in the range of
|
|
|
|
/// `-180.0` up until including `180.0` degrees.
|
2022-09-29 21:25:01 +02:00
|
|
|
longitude: f64,
|
|
|
|
|
2022-09-27 17:10:45 +02:00
|
|
|
/// The altitude coordinate of a location, if provided.
|
2022-09-29 19:53:07 +02:00
|
|
|
#[builder(default, setter(strip_option))]
|
2022-09-29 21:25:01 +02:00
|
|
|
altitude: Option<f64>,
|
|
|
|
|
2022-09-29 19:53:07 +02:00
|
|
|
#[builder(default, setter(strip_option))]
|
2022-09-27 17:10:45 +02:00
|
|
|
/// The uncertainty around the location as a radius (distance) in meters.
|
2022-09-29 22:15:28 +02:00
|
|
|
///
|
|
|
|
/// This distance needs to be positive.
|
|
|
|
uncertainty: Option<f64>,
|
2022-09-27 17:10:45 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
impl GeoUri {
|
2022-09-29 19:52:49 +02:00
|
|
|
/// Return a builder for `GeoUri`.
|
2022-09-27 17:10:45 +02:00
|
|
|
pub fn builder() -> GeoUriBuilder {
|
|
|
|
GeoUriBuilder::default()
|
|
|
|
}
|
|
|
|
|
2022-09-29 19:52:49 +02:00
|
|
|
/// Try parsing a geo URI string into a `GeoUri`.
|
2022-09-27 17:10:45 +02:00
|
|
|
///
|
|
|
|
/// For the geo URI scheme syntax, see the propsed IEEE standard
|
|
|
|
/// [RFC 5870](https://www.rfc-editor.org/rfc/rfc5870#section-3.3).
|
2022-09-29 20:56:48 +02:00
|
|
|
pub fn parse(uri: &str) -> Result<Self, Error> {
|
2022-09-29 21:28:14 +02:00
|
|
|
let uri = uri.to_ascii_lowercase();
|
2022-09-29 20:56:48 +02:00
|
|
|
let uri_path = uri.strip_prefix("geo:").ok_or(Error::MissingScheme)?;
|
2022-09-27 17:10:45 +02:00
|
|
|
let mut parts = uri_path.split(';');
|
|
|
|
|
|
|
|
// Parse the coordinate part.
|
|
|
|
let coords_part = parts.next().expect("Split always yields at least one part");
|
|
|
|
// Don't iterate over anything if the coordinate part is empty!
|
|
|
|
let mut coords = if coords_part.is_empty() {
|
2022-09-29 20:56:48 +02:00
|
|
|
return Err(Error::MissingCoords);
|
2022-09-27 17:10:45 +02:00
|
|
|
} else {
|
|
|
|
coords_part.splitn(3, ',')
|
|
|
|
};
|
|
|
|
let latitude = coords
|
|
|
|
.next()
|
2022-09-29 20:56:48 +02:00
|
|
|
.ok_or(Error::MissingLatitude) // This cannot really happen
|
|
|
|
.and_then(|lat_s| lat_s.parse().map_err(Error::InvalidCoord))?;
|
2022-09-27 17:10:45 +02:00
|
|
|
|
|
|
|
let longitude = coords
|
|
|
|
.next()
|
2022-09-29 20:56:48 +02:00
|
|
|
.ok_or(Error::MissingLongitude)
|
|
|
|
.and_then(|lon_s| lon_s.parse().map_err(Error::InvalidCoord))?;
|
2022-09-27 17:10:45 +02:00
|
|
|
|
|
|
|
let altitude = coords
|
|
|
|
.next()
|
2022-09-29 20:56:48 +02:00
|
|
|
.map(|alt_s| alt_s.parse().map_err(Error::InvalidCoord))
|
2022-09-27 17:10:45 +02:00
|
|
|
.transpose()?;
|
|
|
|
|
|
|
|
// Parse the remaining (parameters) parts.
|
|
|
|
//
|
|
|
|
// TODO: Handle percent encoding of the parameters.
|
|
|
|
//
|
|
|
|
// If the "crs" parameter is passed, its value must be "wgs84" or it is unsupported.
|
|
|
|
// It can be followed by a "u" parameter or that can be the first one.
|
|
|
|
// All other parameters are ignored.
|
|
|
|
let mut param_parts = parts.flat_map(|part| part.split_once('='));
|
2022-09-29 20:51:30 +02:00
|
|
|
let (crs, uncertainty) = match param_parts.next() {
|
2022-09-27 17:10:45 +02:00
|
|
|
Some(("crs", value)) => {
|
2022-09-29 21:28:14 +02:00
|
|
|
if value != "wgs84" {
|
2022-09-29 20:56:48 +02:00
|
|
|
return Err(Error::InvalidCoordRefSystem);
|
2022-09-27 17:10:45 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
match param_parts.next() {
|
|
|
|
Some(("u", value)) => (
|
2022-09-29 20:51:30 +02:00
|
|
|
CoordRefSystem::Wgs84,
|
2022-09-29 22:15:28 +02:00
|
|
|
Some(value.parse().map_err(Error::InvalidUncertainty)?),
|
2022-09-27 17:10:45 +02:00
|
|
|
),
|
2022-09-29 20:51:30 +02:00
|
|
|
Some(_) | None => (CoordRefSystem::Wgs84, None),
|
2022-09-27 17:10:45 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
Some(("u", value)) => (
|
2022-09-29 20:51:30 +02:00
|
|
|
CoordRefSystem::default(),
|
2022-09-29 22:15:28 +02:00
|
|
|
Some(value.parse().map_err(Error::InvalidUncertainty)?),
|
2022-09-27 17:10:45 +02:00
|
|
|
),
|
2022-09-29 20:51:30 +02:00
|
|
|
Some(_) | None => (CoordRefSystem::default(), None),
|
2022-09-27 17:10:45 +02:00
|
|
|
};
|
|
|
|
|
2022-09-29 22:15:28 +02:00
|
|
|
// Validate the parsed values.
|
2022-09-29 20:51:30 +02:00
|
|
|
crs.validate(latitude, longitude)?;
|
2022-09-29 22:15:28 +02:00
|
|
|
// FIXME: Move this into the validator? This code is duplicate now.
|
|
|
|
if let Some(unc) = uncertainty {
|
|
|
|
if unc < 0.0 {
|
|
|
|
return Err(Error::OutOfRangeUncertainty);
|
|
|
|
}
|
|
|
|
}
|
2022-09-29 20:51:30 +02:00
|
|
|
|
2022-09-27 17:10:45 +02:00
|
|
|
Ok(GeoUri {
|
2022-09-29 20:51:30 +02:00
|
|
|
crs,
|
2022-09-27 17:10:45 +02:00
|
|
|
latitude,
|
|
|
|
longitude,
|
|
|
|
altitude,
|
|
|
|
uncertainty,
|
|
|
|
})
|
|
|
|
}
|
2022-09-29 21:25:01 +02:00
|
|
|
|
|
|
|
/// Returns the latitude coordinate.
|
|
|
|
pub fn latitude(&self) -> f64 {
|
|
|
|
self.latitude
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Changes the latitude coordinate.
|
|
|
|
///
|
|
|
|
/// The latitude may be out of range for the coordinate reference system.
|
|
|
|
pub fn set_latitude(&mut self, latitude: f64) -> Result<(), Error> {
|
|
|
|
self.crs.validate(latitude, self.longitude)?;
|
|
|
|
self.latitude = latitude;
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns the longitude coordinate.
|
|
|
|
pub fn longitude(&self) -> f64 {
|
|
|
|
self.longitude
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Changes the longitude coordinate.
|
|
|
|
///
|
|
|
|
/// The longitude may be out of range for the coordinate reference system.
|
|
|
|
pub fn set_longitude(&mut self, longitude: f64) -> Result<(), Error> {
|
|
|
|
self.crs.validate(self.latitude, longitude)?;
|
|
|
|
self.longitude = longitude;
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns the altitude coordinate (if any).
|
|
|
|
pub fn altitude(&self) -> Option<f64> {
|
|
|
|
self.altitude
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Changes the altitude coordinate.
|
|
|
|
pub fn set_altitude(&mut self, altitude: Option<f64>) {
|
|
|
|
self.altitude = altitude;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns the uncertainty around the location.
|
2022-09-29 22:15:28 +02:00
|
|
|
pub fn uncertainty(&self) -> Option<f64> {
|
2022-09-29 21:25:01 +02:00
|
|
|
self.uncertainty
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Changes the uncertainty around the location.
|
2022-09-29 22:15:28 +02:00
|
|
|
///
|
|
|
|
/// The uncertainty distance must be positive.
|
|
|
|
pub fn set_uncertainty(&mut self, uncertainty: Option<f64>) -> Result<(), Error> {
|
|
|
|
if let Some(unc) = uncertainty {
|
|
|
|
if unc < 0.0 {
|
|
|
|
return Err(Error::OutOfRangeUncertainty);
|
|
|
|
}
|
|
|
|
}
|
2022-09-29 21:25:01 +02:00
|
|
|
self.uncertainty = uncertainty;
|
2022-09-29 22:15:28 +02:00
|
|
|
|
|
|
|
Ok(())
|
2022-09-29 21:25:01 +02:00
|
|
|
}
|
2022-09-27 17:10:45 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
impl fmt::Display for GeoUri {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
|
|
let Self {
|
|
|
|
latitude,
|
|
|
|
longitude,
|
|
|
|
..
|
|
|
|
} = self;
|
|
|
|
write!(f, "{URI_SCHEME_NAME}:{latitude},{longitude}")?;
|
|
|
|
|
|
|
|
if let Some(altitude) = self.altitude {
|
2022-09-29 20:22:23 +02:00
|
|
|
write!(f, ",{altitude}")?;
|
2022-09-27 17:10:45 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Don't write the CRS since there is only one supported at the moment.
|
|
|
|
if let Some(uncertainty) = self.uncertainty {
|
|
|
|
write!(f, ";u={uncertainty}")?;
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl FromStr for GeoUri {
|
2022-09-29 20:56:48 +02:00
|
|
|
type Err = Error;
|
2022-09-27 17:10:45 +02:00
|
|
|
|
|
|
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
|
|
|
Self::parse(s)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl TryFrom<&str> for GeoUri {
|
2022-09-29 20:56:48 +02:00
|
|
|
type Error = Error;
|
2022-09-27 17:10:45 +02:00
|
|
|
|
|
|
|
fn try_from(value: &str) -> Result<Self, Self::Error> {
|
|
|
|
Self::parse(value)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl PartialEq for GeoUri {
|
|
|
|
fn eq(&self, other: &Self) -> bool {
|
|
|
|
// In the WGS-84 CRS the the longitude is ignored for the poles.
|
2022-09-29 20:51:30 +02:00
|
|
|
let ignore_longitude = self.crs == CoordRefSystem::Wgs84 && self.latitude.abs() == 90.0;
|
2022-09-27 17:10:45 +02:00
|
|
|
|
2022-09-29 20:51:30 +02:00
|
|
|
self.crs == other.crs
|
2022-09-27 17:10:45 +02:00
|
|
|
&& self.latitude == other.latitude
|
|
|
|
&& (ignore_longitude || self.longitude == other.longitude)
|
|
|
|
&& self.altitude == other.altitude
|
|
|
|
&& self.uncertainty == other.uncertainty
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-09-29 20:51:30 +02:00
|
|
|
impl GeoUriBuilder {
|
|
|
|
/// Validates the coordinates against the
|
|
|
|
fn validate(&self) -> Result<(), String> {
|
|
|
|
self.crs
|
|
|
|
.unwrap_or_default()
|
|
|
|
.validate(
|
|
|
|
self.latitude.unwrap_or_default(),
|
|
|
|
self.longitude.unwrap_or_default(),
|
|
|
|
)
|
2022-09-29 22:15:28 +02:00
|
|
|
.map_err(|e| format!("{e}"))?;
|
|
|
|
|
|
|
|
if let Some(unc) = self.uncertainty.unwrap_or_default() {
|
|
|
|
if unc < 0.0 {
|
|
|
|
return Err(format!("{}", Error::OutOfRangeUncertainty));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
2022-09-29 20:51:30 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-09-27 17:10:45 +02:00
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
use float_eq::assert_float_eq;
|
|
|
|
|
|
|
|
use super::*;
|
|
|
|
|
|
|
|
#[test]
|
2022-09-29 20:51:30 +02:00
|
|
|
fn coord_ref_system_default() {
|
|
|
|
assert_eq!(CoordRefSystem::default(), CoordRefSystem::Wgs84);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn coord_ref_system_validate() {
|
|
|
|
let crs = CoordRefSystem::Wgs84;
|
|
|
|
assert_eq!(crs.validate(52.107, 5.134), Ok(()));
|
2022-09-29 20:56:48 +02:00
|
|
|
assert_eq!(crs.validate(100.0, 5.134), Err(Error::OutOfRangeLatitude));
|
2022-09-29 20:51:30 +02:00
|
|
|
assert_eq!(
|
|
|
|
crs.validate(51.107, -200.0),
|
2022-09-29 20:56:48 +02:00
|
|
|
Err(Error::OutOfRangeLongitude)
|
2022-09-29 20:51:30 +02:00
|
|
|
);
|
2022-09-29 20:22:23 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2022-09-29 21:45:00 +02:00
|
|
|
fn geo_uri_builder() -> Result<(), GeoUriBuilderError> {
|
|
|
|
let mut builder = GeoUri::builder();
|
|
|
|
assert!(matches!(
|
|
|
|
builder.build(),
|
|
|
|
Err(GeoUriBuilderError::UninitializedField("latitude"))
|
|
|
|
));
|
|
|
|
|
|
|
|
builder.latitude(52.107);
|
|
|
|
assert!(matches!(
|
|
|
|
builder.build(),
|
|
|
|
Err(GeoUriBuilderError::UninitializedField("longitude"))
|
|
|
|
));
|
|
|
|
|
|
|
|
builder.longitude(5.134);
|
|
|
|
let geo_uri = builder.build()?;
|
|
|
|
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);
|
2022-09-29 21:25:01 +02:00
|
|
|
|
2022-09-29 21:45:00 +02:00
|
|
|
builder.latitude(100.0);
|
|
|
|
assert!(matches!(
|
|
|
|
builder.build(),
|
|
|
|
Err(GeoUriBuilderError::ValidationError(_))
|
|
|
|
));
|
|
|
|
|
|
|
|
builder.latitude(52.107).longitude(-200.0);
|
|
|
|
assert!(matches!(
|
|
|
|
builder.build(),
|
|
|
|
Err(GeoUriBuilderError::ValidationError(_))
|
|
|
|
));
|
|
|
|
|
|
|
|
Ok(())
|
2022-09-29 20:22:23 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2022-09-29 20:56:48 +02:00
|
|
|
fn geo_uri_parse() -> Result<(), Error> {
|
2022-09-27 17:10:45 +02:00
|
|
|
let geo_uri = GeoUri::parse("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);
|
2022-09-29 20:22:23 +02:00
|
|
|
assert_eq!(geo_uri.altitude, None);
|
2022-09-27 17:10:45 +02:00
|
|
|
assert_eq!(geo_uri.uncertainty, None);
|
|
|
|
|
|
|
|
let geo_uri = GeoUri::parse("52.107,5.134");
|
2022-09-29 20:56:48 +02:00
|
|
|
assert!(matches!(geo_uri, Err(Error::MissingScheme)));
|
2022-09-27 17:10:45 +02:00
|
|
|
|
2022-09-29 22:15:28 +02:00
|
|
|
let geo_uri = GeoUri::parse("geo:100.0,5.134");
|
|
|
|
assert!(matches!(geo_uri, Err(Error::OutOfRangeLatitude)));
|
|
|
|
|
|
|
|
let geo_uri = GeoUri::parse("geo:62.107,-200.0");
|
|
|
|
assert!(matches!(geo_uri, Err(Error::OutOfRangeLongitude)));
|
|
|
|
|
2022-09-27 17:10:45 +02:00
|
|
|
let geo_uri = GeoUri::parse("geo:geo:52.107,5.134");
|
2022-09-29 20:56:48 +02:00
|
|
|
assert!(matches!(geo_uri, Err(Error::InvalidCoord(_))));
|
2022-09-27 17:10:45 +02:00
|
|
|
|
|
|
|
let geo_uri = GeoUri::parse("geo:");
|
2022-09-29 20:56:48 +02:00
|
|
|
assert!(matches!(geo_uri, Err(Error::MissingCoords)));
|
2022-09-27 17:10:45 +02:00
|
|
|
|
|
|
|
let geo_uri = GeoUri::parse("geo:;u=5000");
|
2022-09-29 20:56:48 +02:00
|
|
|
assert!(matches!(geo_uri, Err(Error::MissingCoords)));
|
2022-09-27 17:10:45 +02:00
|
|
|
|
|
|
|
let geo_uri = GeoUri::parse("geo:52.107;u=1000");
|
2022-09-29 20:56:48 +02:00
|
|
|
assert!(matches!(geo_uri, Err(Error::MissingLongitude)));
|
2022-09-27 17:10:45 +02:00
|
|
|
|
|
|
|
let geo_uri = GeoUri::parse("geo:52.107,;u=1000");
|
2022-09-29 20:56:48 +02:00
|
|
|
assert!(matches!(geo_uri, Err(Error::InvalidCoord(_))));
|
2022-09-27 17:10:45 +02:00
|
|
|
|
2022-09-29 20:22:23 +02:00
|
|
|
let geo_uri = GeoUri::parse("geo:52.107,,6.50;u=1000");
|
2022-09-29 20:56:48 +02:00
|
|
|
assert!(matches!(geo_uri, Err(Error::InvalidCoord(_))));
|
2022-09-27 17:10:45 +02:00
|
|
|
|
|
|
|
let geo_uri = GeoUri::parse("geo:52.107,5.134,;u=1000");
|
2022-09-29 20:56:48 +02:00
|
|
|
assert!(matches!(geo_uri, Err(Error::InvalidCoord(_))));
|
2022-09-27 17:10:45 +02:00
|
|
|
|
|
|
|
let geo_uri = GeoUri::parse("geo:52.107,5.134,3.6")?;
|
|
|
|
assert_float_eq!(geo_uri.latitude, 52.107, abs <= 0.001);
|
|
|
|
assert_float_eq!(geo_uri.longitude, 5.134, abs <= 0.001);
|
2022-09-29 22:24:00 +02:00
|
|
|
assert_float_eq!(geo_uri.altitude.unwrap(), 3.6, abs <= 0.1);
|
2022-09-27 17:10:45 +02:00
|
|
|
assert_eq!(geo_uri.uncertainty, None);
|
|
|
|
|
2022-09-29 20:22:23 +02:00
|
|
|
let geo_uri = GeoUri::parse("geo:52.107,5.34,3.6;u=");
|
2022-09-29 22:15:28 +02:00
|
|
|
assert!(matches!(geo_uri, Err(Error::InvalidUncertainty(_))));
|
2022-09-27 17:10:45 +02:00
|
|
|
|
2022-09-29 20:22:23 +02:00
|
|
|
let geo_uri = GeoUri::parse("geo:52.107,5.34,3.6;u=foo");
|
2022-09-29 22:15:28 +02:00
|
|
|
assert!(matches!(geo_uri, Err(Error::InvalidUncertainty(_))));
|
2022-09-27 17:10:45 +02:00
|
|
|
|
2022-09-29 20:22:23 +02:00
|
|
|
let geo_uri = GeoUri::parse("geo:52.107,5.34,3.6;crs=wgs84;u=foo");
|
2022-09-29 22:15:28 +02:00
|
|
|
assert!(matches!(geo_uri, Err(Error::InvalidUncertainty(_))));
|
|
|
|
|
|
|
|
let geo_uri = GeoUri::parse("geo:52.107,5.34,3.6;u=-10.0");
|
|
|
|
assert!(matches!(geo_uri, Err(Error::OutOfRangeUncertainty)));
|
2022-09-27 17:10:45 +02:00
|
|
|
|
2022-09-29 20:22:23 +02:00
|
|
|
let geo_uri = GeoUri::parse("geo:52.107,5.134,3.6;u=25000")?;
|
2022-09-27 17:10:45 +02:00
|
|
|
assert_float_eq!(geo_uri.latitude, 52.107, abs <= 0.001);
|
|
|
|
assert_float_eq!(geo_uri.longitude, 5.134, abs <= 0.001);
|
2022-09-29 22:24:00 +02:00
|
|
|
assert_float_eq!(geo_uri.altitude.unwrap(), 3.6, abs <= 0.1);
|
2022-09-29 22:15:28 +02:00
|
|
|
assert_eq!(geo_uri.uncertainty, Some(25_000.0));
|
2022-09-27 17:10:45 +02:00
|
|
|
|
2022-09-29 20:22:23 +02:00
|
|
|
let geo_uri = GeoUri::parse("geo:52.107,5.134,3.6;crs=wgs84;u=25000")?;
|
2022-09-27 17:10:45 +02:00
|
|
|
assert_float_eq!(geo_uri.latitude, 52.107, abs <= 0.001);
|
|
|
|
assert_float_eq!(geo_uri.longitude, 5.134, abs <= 0.001);
|
2022-09-29 22:24:00 +02:00
|
|
|
assert_float_eq!(geo_uri.altitude.unwrap(), 3.6, abs <= 0.1);
|
2022-09-29 22:15:28 +02:00
|
|
|
assert_eq!(geo_uri.uncertainty, Some(25_000.0));
|
2022-09-27 17:10:45 +02:00
|
|
|
|
2022-09-29 21:28:14 +02:00
|
|
|
let geo_uri = GeoUri::parse("geo:52.107,5.134,3.6;CRS=wgs84;U=25000")?;
|
2022-09-29 22:15:28 +02:00
|
|
|
assert_eq!(geo_uri.uncertainty, Some(25_000.0));
|
2022-09-29 21:28:14 +02:00
|
|
|
|
2022-09-29 20:22:23 +02:00
|
|
|
let geo_uri = GeoUri::parse("geo:52.107,5.134,3.6;crs=wgs84;u=25000;foo=bar")?;
|
2022-09-27 17:10:45 +02:00
|
|
|
assert_float_eq!(geo_uri.latitude, 52.107, abs <= 0.001);
|
|
|
|
assert_float_eq!(geo_uri.longitude, 5.134, abs <= 0.001);
|
2022-09-29 22:24:00 +02:00
|
|
|
assert_float_eq!(geo_uri.altitude.unwrap(), 3.6, abs <= 0.1);
|
2022-09-29 22:15:28 +02:00
|
|
|
assert_eq!(geo_uri.uncertainty, Some(25_000.0));
|
2022-09-27 17:10:45 +02:00
|
|
|
|
2022-09-29 20:22:23 +02:00
|
|
|
let geo_uri = GeoUri::parse("geo:52.107,5.34,3.6;crs=foo");
|
2022-09-29 20:56:48 +02:00
|
|
|
assert!(matches!(geo_uri, Err(Error::InvalidCoordRefSystem)));
|
2022-09-27 17:10:45 +02:00
|
|
|
|
2022-09-29 20:22:23 +02:00
|
|
|
let geo_uri = GeoUri::parse("geo:52.107,5.34,3.6;crs=wgs84")?;
|
2022-09-29 20:51:30 +02:00
|
|
|
assert!(matches!(geo_uri.crs, CoordRefSystem::Wgs84));
|
2022-09-27 17:10:45 +02:00
|
|
|
|
2022-09-29 22:24:00 +02:00
|
|
|
// Examples from RFC 5870 (sections 1, 6.1, 6.2 and 9.4)!
|
|
|
|
let geo_uri = GeoUri::parse("geo:13.4125,103.8667")?;
|
|
|
|
assert_float_eq!(geo_uri.latitude, 13.4125, abs <= 0.0001);
|
|
|
|
assert_float_eq!(geo_uri.longitude, 103.8667, abs <= 0.0001);
|
|
|
|
assert_eq!(geo_uri.altitude, None);
|
|
|
|
assert_eq!(geo_uri.uncertainty, None);
|
|
|
|
|
|
|
|
let geo_uri = GeoUri::parse("geo:48.2010,16.3695,183")?;
|
|
|
|
assert_float_eq!(geo_uri.latitude, 48.2010, abs <= 0.0001);
|
|
|
|
assert_float_eq!(geo_uri.longitude, 16.3695, abs <= 0.0001);
|
|
|
|
assert_float_eq!(geo_uri.altitude.unwrap(), 183.0, abs <= 0.1);
|
|
|
|
assert_eq!(geo_uri.uncertainty, None);
|
|
|
|
|
|
|
|
let geo_uri = GeoUri::parse("geo:48.198634,16.371648;crs=wgs84;u=40")?;
|
|
|
|
assert_eq!(geo_uri.crs, CoordRefSystem::Wgs84);
|
|
|
|
assert_float_eq!(geo_uri.latitude, 48.198634, abs <= 0.000001);
|
|
|
|
assert_float_eq!(geo_uri.longitude, 16.371648, abs <= 0.000001);
|
|
|
|
assert_eq!(geo_uri.altitude, None);
|
|
|
|
assert_eq!(geo_uri.uncertainty, Some(40.0));
|
|
|
|
|
|
|
|
let geo_uri = GeoUri::parse("geo:94,0");
|
|
|
|
assert_eq!(geo_uri, Err(Error::OutOfRangeLatitude));
|
2022-09-27 17:10:45 +02:00
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2022-09-29 21:25:01 +02:00
|
|
|
#[test]
|
|
|
|
fn geo_uri_get_set() {
|
|
|
|
let mut geo_uri = GeoUri {
|
|
|
|
crs: CoordRefSystem::Wgs84,
|
|
|
|
latitude: 52.107,
|
|
|
|
longitude: 5.134,
|
|
|
|
altitude: None,
|
|
|
|
uncertainty: None,
|
|
|
|
};
|
|
|
|
assert_eq!(geo_uri.latitude(), 52.107);
|
|
|
|
assert_eq!(geo_uri.longitude(), 5.134);
|
|
|
|
assert_eq!(geo_uri.altitude(), None);
|
|
|
|
assert_eq!(geo_uri.uncertainty(), None);
|
|
|
|
|
|
|
|
assert_eq!(geo_uri.set_latitude(53.107), Ok(()));
|
|
|
|
assert_eq!(geo_uri.set_latitude(100.0), Err(Error::OutOfRangeLatitude));
|
|
|
|
assert_eq!(geo_uri.latitude(), 53.107);
|
|
|
|
|
|
|
|
assert_eq!(geo_uri.set_longitude(6.134), Ok(()));
|
|
|
|
assert_eq!(
|
|
|
|
geo_uri.set_longitude(-200.0),
|
|
|
|
Err(Error::OutOfRangeLongitude)
|
|
|
|
);
|
|
|
|
assert_eq!(geo_uri.longitude(), 6.134);
|
|
|
|
|
|
|
|
geo_uri.set_altitude(Some(3.6));
|
|
|
|
assert_eq!(geo_uri.altitude(), Some(3.6));
|
|
|
|
|
2022-09-29 22:15:28 +02:00
|
|
|
assert_eq!(geo_uri.set_uncertainty(Some(25_000.0)), Ok(()));
|
|
|
|
assert_eq!(
|
|
|
|
geo_uri.set_uncertainty(Some(-100.0)),
|
|
|
|
Err(Error::OutOfRangeUncertainty)
|
|
|
|
);
|
|
|
|
assert_eq!(geo_uri.uncertainty(), Some(25_000.0));
|
2022-09-29 21:25:01 +02:00
|
|
|
}
|
|
|
|
|
2022-09-27 17:10:45 +02:00
|
|
|
#[test]
|
2022-09-29 20:22:23 +02:00
|
|
|
fn geo_uri_display() {
|
|
|
|
let mut geo_uri = GeoUri {
|
2022-09-29 20:51:30 +02:00
|
|
|
crs: CoordRefSystem::Wgs84,
|
2022-09-29 20:22:23 +02:00
|
|
|
latitude: 52.107,
|
|
|
|
longitude: 5.134,
|
|
|
|
altitude: None,
|
|
|
|
uncertainty: None,
|
|
|
|
};
|
|
|
|
assert_eq!(&geo_uri.to_string(), "geo:52.107,5.134");
|
|
|
|
|
|
|
|
geo_uri.altitude = Some(3.6);
|
|
|
|
assert_eq!(&geo_uri.to_string(), "geo:52.107,5.134,3.6");
|
|
|
|
|
2022-09-29 22:15:28 +02:00
|
|
|
geo_uri.uncertainty = Some(25_000.0);
|
2022-09-29 20:22:23 +02:00
|
|
|
assert_eq!(&geo_uri.to_string(), "geo:52.107,5.134,3.6;u=25000");
|
2022-09-27 17:10:45 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2022-09-29 20:56:48 +02:00
|
|
|
fn geo_uri_from_str() -> Result<(), Error> {
|
2022-09-29 20:22:23 +02:00
|
|
|
let geo_uri = GeoUri::from_str("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);
|
|
|
|
|
|
|
|
Ok(())
|
2022-09-27 17:10:45 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2022-09-29 20:56:48 +02:00
|
|
|
fn geo_uri_try_from() -> Result<(), Error> {
|
2022-09-29 20:22:23 +02:00
|
|
|
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);
|
|
|
|
|
|
|
|
Ok(())
|
2022-09-27 17:10:45 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2022-09-29 20:22:23 +02:00
|
|
|
fn geo_uri_partial_eq() -> Result<(), GeoUriBuilderError> {
|
|
|
|
let geo_uri = GeoUri::builder()
|
|
|
|
.latitude(52.107)
|
|
|
|
.longitude(5.134)
|
|
|
|
.build()?;
|
|
|
|
let geo_uri2 = GeoUri::builder()
|
|
|
|
.latitude(52.107)
|
|
|
|
.longitude(5.134)
|
|
|
|
.build()?;
|
|
|
|
assert_eq!(geo_uri, geo_uri2);
|
|
|
|
assert_eq!(geo_uri, geo_uri.clone());
|
|
|
|
|
|
|
|
let geo_uri = GeoUri::builder().latitude(90.0).longitude(5.134).build()?;
|
|
|
|
let geo_uri2 = GeoUri::builder().latitude(90.0).longitude(5.134).build()?;
|
|
|
|
assert_eq!(geo_uri, geo_uri2);
|
|
|
|
|
|
|
|
let geo_uri = GeoUri::builder().latitude(-90.0).longitude(5.134).build()?;
|
|
|
|
let geo_uri2 = GeoUri::builder().latitude(-90.0).longitude(5.134).build()?;
|
|
|
|
assert_eq!(geo_uri, geo_uri2);
|
|
|
|
|
2022-09-29 22:24:00 +02:00
|
|
|
// Examples from RFC 5870 (section 6.4)!
|
|
|
|
let geo_uri = GeoUri::parse("geo:90,-22.43;crs=WGS84").expect("parsable geo URI");
|
|
|
|
let geo_uri2 = GeoUri::parse("geo:90,46").expect("parsable geo URI");
|
|
|
|
assert_eq!(geo_uri, geo_uri2);
|
|
|
|
|
|
|
|
let geo_uri = GeoUri::parse("geo:22.300,-118.44").expect("parsable geo URI");
|
|
|
|
let geo_uri2 = GeoUri::parse("geo:22.3,-118.4400").expect("parsable geo URI");
|
|
|
|
assert_eq!(geo_uri, geo_uri2);
|
|
|
|
|
|
|
|
let geo_uri = GeoUri::parse("geo:66,30;u=6.500;FOo=this%2dthat").expect("parsable geo URI");
|
|
|
|
let geo_uri2 = GeoUri::parse("geo:66.0,30;u=6.5;foo=this-that").expect("parsable geo URI");
|
|
|
|
assert_eq!(geo_uri, geo_uri2);
|
|
|
|
|
|
|
|
let _geo_uri = GeoUri::parse("geo:70,20;foo=1.00;bar=white").expect("parsable geo URI");
|
|
|
|
let _geo_uri2 = GeoUri::parse("geo:70,20;foo=1;bar=white").expect("parsable geo URI");
|
|
|
|
// This is undefined!
|
|
|
|
// assert_eq!(geo_uri, geo_uri2);
|
|
|
|
|
|
|
|
let geo_uri = GeoUri::parse("geo:47,11;foo=blue;bar=white").expect("parsable geo URI");
|
|
|
|
let geo_uri2 = GeoUri::parse("geo:47,11;bar=white;foo=blue").expect("parsable geo URI");
|
|
|
|
assert_eq!(geo_uri, geo_uri2);
|
|
|
|
|
|
|
|
let _geo_uri = GeoUri::parse("geo:22,0;bar=Blue").expect("parsable geo URI");
|
|
|
|
let _geo_uri2 = GeoUri::parse("geo:22,0;BAR=blue").expect("parsable geo URI");
|
|
|
|
// This is undefined!
|
|
|
|
// assert_eq!(geo_uri, geo_uri2);
|
|
|
|
|
2022-09-29 20:22:23 +02:00
|
|
|
Ok(())
|
2022-09-27 17:10:45 +02:00
|
|
|
}
|
|
|
|
}
|