Add getters/setters for `GeoUri`

Also make all of its fields private.
This prevents parsing/building a valid geo URI and then making it
invalid by setting the latitude/longitude to something incorrect.
This commit is contained in:
Paul van Tilburg 2022-09-29 21:25:01 +02:00
parent e526fa0c5e
commit 3e2584dcda
Signed by: paul
GPG Key ID: C6DE073EDA9EEC4D
1 changed files with 113 additions and 16 deletions

View File

@ -135,8 +135,11 @@ impl Default for CoordRefSystem {
/// ```rust /// ```rust
/// use geo_uri::GeoUri; /// use geo_uri::GeoUri;
/// ///
/// let geo_uri = GeoUri::try_from("geo:52.107,5.134,3.6;u=1000"); /// let geo_uri = GeoUri::try_from("geo:52.107,5.134,3.6;u=1000").expect("valid geo URI");
/// assert!(geo_uri.is_ok()); /// 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(), Some(1000));
/// ``` /// ```
/// ///
/// or by using the [`TryFrom`] trait: /// or by using the [`TryFrom`] trait:
@ -144,8 +147,11 @@ impl Default for CoordRefSystem {
/// use geo_uri::GeoUri; /// use geo_uri::GeoUri;
/// use std::str::FromStr; /// use std::str::FromStr;
/// ///
/// let geo_uri = GeoUri::from_str("geo:52.107,5.134;u=2000"); /// let geo_uri = GeoUri::from_str("geo:52.107,5.134;u=2000").expect("valid geo URI");
/// assert!(geo_uri.is_ok()); /// 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(), Some(2000));
/// ``` /// ```
/// ///
/// It is also possible to call the parse function directly: /// It is also possible to call the parse function directly:
@ -153,8 +159,11 @@ impl Default for CoordRefSystem {
/// ```rust /// ```rust
/// use geo_uri::GeoUri; /// use geo_uri::GeoUri;
/// ///
/// let geo_uri = GeoUri::parse("geo:52.107,5.134,3.6;u=1000"); /// let geo_uri = GeoUri::parse("geo:52.107,5.134,3.6").expect("valid geo URI");
/// assert!(geo_uri.is_ok()); /// 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);
/// ``` /// ```
/// ///
/// ## Generating /// ## Generating
@ -165,11 +174,11 @@ impl Default for CoordRefSystem {
/// use geo_uri::GeoUri; /// use geo_uri::GeoUri;
/// ///
/// let geo_uri = GeoUri::builder() /// let geo_uri = GeoUri::builder()
/// .latitude(52.107) /// .latitude(52.107)
/// .longitude(5.134) /// .longitude(5.134)
/// .uncertainty(1_000) /// .uncertainty(1_000)
/// .build() /// .build()
/// .unwrap(); /// .unwrap();
/// assert_eq!( /// assert_eq!(
/// geo_uri.to_string(), /// geo_uri.to_string(),
/// String::from("geo:52.107,5.134;u=1000") /// String::from("geo:52.107,5.134;u=1000")
@ -188,23 +197,27 @@ impl Default for CoordRefSystem {
pub struct GeoUri { pub struct GeoUri {
/// The coordinate reference system used by the coordinates of this URI. /// The coordinate reference system used by the coordinates of this URI.
#[builder(default)] #[builder(default)]
pub crs: CoordRefSystem, crs: CoordRefSystem,
/// The latitude coordinate of a location. /// The latitude coordinate of a location.
/// ///
/// For the WGS-84 coordinate reference system, this should be in the range of /// For the WGS-84 coordinate reference system, this should be in the range of
/// `-90.0` up until including `90.0` degrees. /// `-90.0` up until including `90.0` degrees.
pub latitude: f64, latitude: f64,
/// The longitude coordinate of a location. /// The longitude coordinate of a location.
/// ///
/// For the WGS-84 coordinate reference system, this should be in the range of /// For the WGS-84 coordinate reference system, this should be in the range of
/// `-180.0` up until including `180.0` degrees. /// `-180.0` up until including `180.0` degrees.
pub longitude: f64, longitude: f64,
/// The altitude coordinate of a location, if provided. /// The altitude coordinate of a location, if provided.
#[builder(default, setter(strip_option))] #[builder(default, setter(strip_option))]
pub altitude: Option<f64>, altitude: Option<f64>,
#[builder(default, setter(strip_option))] #[builder(default, setter(strip_option))]
/// The uncertainty around the location as a radius (distance) in meters. /// The uncertainty around the location as a radius (distance) in meters.
pub uncertainty: Option<u32>, uncertainty: Option<u32>,
} }
impl GeoUri { impl GeoUri {
@ -284,6 +297,56 @@ impl GeoUri {
uncertainty, uncertainty,
}) })
} }
/// 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.
pub fn uncertainty(&self) -> Option<u32> {
self.uncertainty
}
/// Changes the uncertainty around the location.
pub fn set_uncertainty(&mut self, uncertainty: Option<u32>) {
self.uncertainty = uncertainty;
}
} }
impl fmt::Display for GeoUri { impl fmt::Display for GeoUri {
@ -376,6 +439,8 @@ mod tests {
fn geo_uri_builder() { fn geo_uri_builder() {
let builder = GeoUri::builder(); let builder = GeoUri::builder();
assert!(matches!(builder, GeoUriBuilder { .. })); assert!(matches!(builder, GeoUriBuilder { .. }));
// TODO: Add more tests that ensure that required and default values are set up correctly.
} }
#[test] #[test]
@ -454,6 +519,38 @@ mod tests {
Ok(()) Ok(())
} }
#[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));
geo_uri.set_uncertainty(Some(25_000));
assert_eq!(geo_uri.uncertainty(), Some(25_000));
}
#[test] #[test]
fn geo_uri_display() { fn geo_uri_display() {
let mut geo_uri = GeoUri { let mut geo_uri = GeoUri {