From ddca7e7df43a3b58ca0197c1925290aa5eb09e77 Mon Sep 17 00:00:00 2001 From: pjsier Date: Mon, 19 Aug 2019 09:31:09 -0500 Subject: [PATCH 1/4] Implement Openstreetmap provider --- src/lib.rs | 4 + src/openstreetmap.rs | 379 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 383 insertions(+) create mode 100644 src/openstreetmap.rs diff --git a/src/lib.rs b/src/lib.rs index 6c59e56..9e45aa7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -29,6 +29,10 @@ use serde::{Deserialize, Deserializer}; pub mod opencage; pub use crate::opencage::Opencage; +// The OpenStreetMap Nominatim geocoding provider +pub mod openstreetmap; +pub use crate::openstreetmap::Openstreetmap; + /// Reverse-geocode a coordinate. /// /// This trait represents the most simple and minimal implementation diff --git a/src/openstreetmap.rs b/src/openstreetmap.rs new file mode 100644 index 0000000..e31055b --- /dev/null +++ b/src/openstreetmap.rs @@ -0,0 +1,379 @@ +//! The [OpenStreetMap Nominatim](https://nominatim.org/) provider. +//! +//! Geocoding methods are implemented on the [`Openstreetmap`](struct.Openstreetmap.html) struct. +//! Please see the [API documentation](https://nominatim.org/release-docs/develop/) for details. +//! +//! While OpenStreetMap's Nominatim API is free, see the [Nominatim Usage Policy](https://operations.osmfoundation.org/policies/nominatim/) +//! for details on usage requirements, including a maximum of 1 request per second. +//! +//! ### Example +//! +//! ``` +//! use geocoding::{Openstreetmap, Forward, Point}; +//! +//! let osm = Openstreetmap::new(); +//! let address = "Schwabing, München"; +//! let res = oc.forward(&address); +//! assert_eq!(res.unwrap(), vec![Point::new(11.5761796, 48.1599218)]); +//! ``` +use crate::Deserialize; +use crate::Point; +use crate::UA_STRING; +use crate::{Client, HeaderMap, HeaderValue, USER_AGENT}; +use crate::{Forward, Reverse}; +use failure::Error; +use num_traits::Float; + +/// An instance of the Openstreetmap geocoding service +pub struct Openstreetmap { + client: Client, + endpoint: String, +} + +/// An instance of a parameter builder for Openstreetmap geocoding +pub struct OpenstreetmapParams<'a> { + query: &'a str, + addressdetails: &'a bool, + viewbox: Option<&'a [f64; 4]>, +} + +impl<'a> OpenstreetmapParams<'a> { + /// Create a new OpenStreetMap parameter builder + /// # Example: + /// + /// ``` + /// use geocoding::{Openstreetmap, OpenstreetmapParams, Point}; + /// + /// let params = OpenstreetmapParams::new(&"UCL CASA") + /// .with_addressdetails(&true) + /// .with_viewbox(&[ + /// -0.13806939125061035, + /// 51.51989264641164, + /// -0.13427138328552246, + /// 51.52319711775629, + /// ]) + /// .build(); + /// ``` + pub fn new(query: &'a str) -> OpenstreetmapParams<'a> { + OpenstreetmapParams { + query, + addressdetails: &false, + viewbox: None, + } + } + + /// Set the `addressdetails` property + pub fn with_addressdetails(&mut self, addressdetails: &'a bool) -> &mut Self { + self.addressdetails = addressdetails; + self + } + + /// Set the `viewbox` property + pub fn with_viewbox(&mut self, viewbox: &'a [f64; 4]) -> &mut Self { + self.viewbox = Some(viewbox); + self + } + + /// Build and return an instance of OpenstreetmapParams + pub fn build(&self) -> OpenstreetmapParams<'a> { + OpenstreetmapParams { + query: self.query, + addressdetails: self.addressdetails, + viewbox: self.viewbox, + } + } +} + +impl Openstreetmap { + /// Create a new Openstreetmap geocoding instance + pub fn new() -> Self { + let mut headers = HeaderMap::new(); + headers.insert(USER_AGENT, HeaderValue::from_static(UA_STRING)); + let client = Client::builder() + .default_headers(headers) + .build() + .expect("Couldn't build a client!"); + Openstreetmap { + client, + endpoint: "https://nominatim.openstreetmap.org/".to_string(), + } + } + + /// A forward-geocoding lookup of an address, returning a full detailed response + /// + /// Accepts an [`OpenstreetmapParams`](struct.OpenstreetmapParams.html) struct for specifying + /// options, including whether to include address details in the response and whether to filter + /// by a bounding box. + /// + /// Please see [the documentation](https://nominatim.org/release-docs/develop/api/Search/) for details. + /// + /// This method passes the `format` parameter to the API. + /// + /// # Examples + /// + /// ``` + /// use geocoding::{Openstreetmap, OpenstreetmapParams, Point}; + /// + /// let osm = Openstreetmap::new(); + /// let params = OpenstreetmapParams::new(&"UCL CASA") + /// .with_addressdetails(&true) + /// .with_viewbox(&[ + /// -0.13806939125061035, + /// 51.51989264641164, + /// -0.13427138328552246, + /// 51.52319711775629, + /// ]) + /// .build(); + /// let res: OpenstreetmapResponse = osm.forward_full(¶ms).unwrap(); + /// let result = res.features[0].properties.clone(); + /// assert_eq!( + /// result.display_name, + /// "UCL, 188, Tottenham Court Road, Holborn, Bloomsbury, London Borough of Camden, London, Greater London, England, W1T 7PQ, UK", + /// ); + /// ``` + pub fn forward_full( + &self, + params: &OpenstreetmapParams, + ) -> Result, Error> + where + T: Float, + for<'de> T: Deserialize<'de>, + { + let format = String::from("geojson"); + let addressdetails = String::from(if *params.addressdetails { "1" } else { "0" }); + // For lifetime issues + let viewbox; + + let mut query = vec![ + (&"q", params.query), + (&"format", &format), + (&"addressdetails", &addressdetails), + ]; + + if let Some(vb) = params.viewbox { + viewbox = vb + .iter() + .map(|f| f.to_string()) + .collect::>() + .join(","); + query.push((&"viewbox", &viewbox)); + } + + let mut resp = self + .client + .get(&format!("{}search", self.endpoint)) + .query(&query) + .send()? + .error_for_status()?; + let res: OpenstreetmapResponse = resp.json()?; + Ok(res) + } +} + +impl Forward for Openstreetmap +where + T: Float, + for<'de> T: Deserialize<'de>, +{ + /// A forward-geocoding lookup of an address. Please see [the documentation](https://nominatim.org/release-docs/develop/api/Search/) for details. + /// + /// This method passes the `format` parameter to the API. + fn forward(&self, place: &str) -> Result>, Error> { + let mut resp = self + .client + .get(&format!("{}search", self.endpoint)) + .query(&[(&"q", place), (&"format", &String::from("geojson"))]) + .send()? + .error_for_status()?; + let res: OpenstreetmapResponse = resp.json()?; + Ok(res + .features + .iter() + .map(|res| Point::new(res.geometry.coordinates.0, res.geometry.coordinates.1)) + .collect()) + } +} + +impl Reverse for Openstreetmap +where + T: Float, + for<'de> T: Deserialize<'de>, +{ + /// A reverse lookup of a point. More detail on the format of the + /// returned `String` can be found [here](https://nominatim.org/release-docs/develop/api/Reverse/) + /// + /// This method passes the `format` parameter to the API. + fn reverse(&self, point: &Point) -> Result { + let mut resp = self + .client + .get(&format!("{}reverse", self.endpoint)) + .query(&[ + (&"lon", &point.x().to_f64().unwrap().to_string()), + (&"lat", &point.y().to_f64().unwrap().to_string()), + (&"format", &String::from("geojson")), + ]) + .send()? + .error_for_status()?; + let res: OpenstreetmapResponse = resp.json()?; + let address = &res.features[0]; + Ok(address.properties.display_name.to_string()) + } +} + +/// The top-level full GeoJSON response returned by a forward-geocoding request +/// +/// See [the documentation](https://nominatim.org/release-docs/develop/api/Search/#geojson) for more details +/// +///```json +///{ +/// "type": "FeatureCollection", +/// "licence": "Data © OpenStreetMap contributors, ODbL 1.0. https://osm.org/copyright", +/// "features": [ +/// { +/// "type": "Feature", +/// "properties": { +/// "place_id": 263681481, +/// "osm_type": "way", +/// "osm_id": 355421084, +/// "display_name": "68, Carrer de Calatrava, les Tres Torres, Sarrià - Sant Gervasi, Barcelona, BCN, Catalonia, 08017, Spain", +/// "place_rank": 30, +/// "category": "building", +/// "type": "apartments", +/// "importance": 0.7409999999999999, +/// "address": { +/// "house_number": "68", +/// "road": "Carrer de Calatrava", +/// "suburb": "les Tres Torres", +/// "city_district": "Sarrià - Sant Gervasi", +/// "city": "Barcelona", +/// "county": "BCN", +/// "state": "Catalonia", +/// "postcode": "08017", +/// "country": "Spain", +/// "country_code": "es" +/// } +/// }, +/// "bbox": [ +/// 2.1284918, +/// 41.401227, +/// 2.128952, +/// 41.4015815 +/// ], +/// "geometry": { +/// "type": "Point", +/// "coordinates": [ +/// 2.12872241167437, +/// 41.40140675 +/// ] +/// } +/// } +/// ] +///} +///``` +#[derive(Debug, Deserialize)] +pub struct OpenstreetmapResponse +where + T: Float, +{ + r#type: String, + licence: String, + features: Vec>, +} + +/// A geocoding result +#[derive(Debug, Deserialize)] +pub struct OpenstreetmapResult +where + T: Float, +{ + pub r#type: String, + pub properties: ResultProperties, + pub bbox: (T, T, T, T), + pub geometry: ResultGeometry, +} + +/// Geocoding result properties +#[derive(Clone, Debug, Deserialize)] +pub struct ResultProperties { + place_id: u64, + osm_type: String, + osm_id: u64, + display_name: String, + place_rank: u64, + category: String, + r#type: String, + importance: f64, + address: Option, +} + +/// Address details in the result object +#[derive(Clone, Debug, Deserialize)] +pub struct AddressDetails { + city: Option, + city_district: Option, + construction: Option, + continent: Option, + country: Option, + country_code: Option, + house_number: Option, + neighbourhood: Option, + postcode: Option, + public_building: Option, + state: Option, + suburb: Option, +} + +/// A geocoding result geometry +#[derive(Debug, Deserialize)] +pub struct ResultGeometry +where + T: Float, +{ + r#type: String, + coordinates: (T, T), +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn forward_full_test() { + let osm = Openstreetmap::new(); + let params = OpenstreetmapParams::new(&"UCL CASA") + .with_addressdetails(&true) + .with_viewbox(&[ + -0.13806939125061035, + 51.51989264641164, + -0.13427138328552246, + 51.52319711775629, + ]) + .build(); + let res: OpenstreetmapResponse = osm.forward_full(¶ms).unwrap(); + let result = res.features[0].properties.clone(); + assert_eq!( + result.display_name, + "UCL, 188, Tottenham Court Road, Holborn, Bloomsbury, London Borough of Camden, London, Greater London, England, W1T 7PQ, UK", + ); + assert_eq!(result.address.unwrap().city.unwrap(), "London"); + } + + #[test] + fn forward_test() { + let osm = Openstreetmap::new(); + let address = "Schwabing, München"; + let res = osm.forward(&address); + assert_eq!(res.unwrap(), vec![Point::new(11.5761796, 48.1599218)]); + } + + #[test] + fn reverse_test() { + let osm = Openstreetmap::new(); + let p = Point::new(2.12870, 41.40139); + let res = osm.reverse(&p); + assert_eq!( + res.unwrap(), + "68, Carrer de Calatrava, les Tres Torres, Sarrià - Sant Gervasi, Barcelona, BCN, CAT, 08017, España", + ); + } +} From 3e611ec5039523c968b0785521df71b5e773b548 Mon Sep 17 00:00:00 2001 From: pjsier Date: Mon, 19 Aug 2019 11:44:59 -0500 Subject: [PATCH 2/4] Use InputBounds in Openstreetmap --- src/lib.rs | 48 +++++++++++++++++++++++++++++++++ src/opencage.rs | 59 ++++------------------------------------ src/openstreetmap.rs | 64 ++++++++++++++++++++++---------------------- 3 files changed, 85 insertions(+), 86 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 9e45aa7..1ddd887 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -91,3 +91,51 @@ where // data. Please pay attention when using returned data to construct Points fn forward(&self, address: &str) -> Result>, Error>; } + +/// Used to specify a bounding box to search within when forward-geocoding +/// +/// - `minimum` refers to the **bottom-left** or **south-west** corner of the bounding box +/// - `maximum` refers to the **top-right** or **north-east** corner of the bounding box. +#[derive(Copy, Clone, Debug)] +pub struct InputBounds +where + T: Float, +{ + pub minimum_lonlat: Point, + pub maximum_lonlat: Point, +} + +impl InputBounds +where + T: Float, +{ + /// Create a new `InputBounds` struct by passing 2 `Point`s defining: + /// - minimum (bottom-left) longitude and latitude coordinates + /// - maximum (top-right) longitude and latitude coordinates + pub fn new(minimum_lonlat: U, maximum_lonlat: U) -> InputBounds + where + U: Into>, + { + InputBounds { + minimum_lonlat: minimum_lonlat.into(), + maximum_lonlat: maximum_lonlat.into(), + } + } +} + +/// Convert borrowed input bounds into the correct String representation +impl From> for String +where + T: Float, +{ + fn from(ip: InputBounds) -> String { + // Return in lon, lat order + format!( + "{},{},{},{}", + ip.minimum_lonlat.x().to_f64().unwrap().to_string(), + ip.minimum_lonlat.y().to_f64().unwrap().to_string(), + ip.maximum_lonlat.x().to_f64().unwrap().to_string(), + ip.maximum_lonlat.y().to_f64().unwrap().to_string() + ) + } +} diff --git a/src/opencage.rs b/src/opencage.rs index 9936281..2669a47 100644 --- a/src/opencage.rs +++ b/src/opencage.rs @@ -26,6 +26,7 @@ use crate::chrono::naive::serde::ts_seconds::deserialize as from_ts; use crate::chrono::NaiveDateTime; use crate::Deserialize; +use crate::InputBounds; use crate::Point; use crate::UA_STRING; use crate::{Client, HeaderMap, HeaderValue, USER_AGENT}; @@ -166,8 +167,7 @@ impl Opencage { /// # Examples /// ///``` - /// use geocoding::{Opencage, Point}; - /// use geocoding::opencage::InputBounds; + /// use geocoding::{Opencage, InputBounds, Point}; /// /// let oc = Opencage::new("dcdbf0d783374909b3debee728c7cc10".to_string()); /// let address = "UCL CASA"; @@ -185,8 +185,8 @@ impl Opencage { /// /// ``` /// // You can pass NOBOX if you don't need bounds. - /// use geocoding::{Opencage, Point}; - /// use geocoding::opencage::{InputBounds, NOBOX}; + /// use geocoding::{Opencage, InputBounds, Point}; + /// use geocoding::opencage::{NOBOX}; /// let oc = Opencage::new("dcdbf0d783374909b3debee728c7cc10".to_string()); /// let address = "UCL CASA"; /// let res = oc.forward_full(&address, NOBOX).unwrap(); @@ -199,8 +199,7 @@ impl Opencage { /// /// ``` /// // There are several ways to construct a Point, such as from a tuple - /// use geocoding::{Opencage, Point}; - /// use geocoding::opencage::InputBounds; + /// use geocoding::{Opencage, InputBounds, Point}; /// let oc = Opencage::new("dcdbf0d783374909b3debee728c7cc10".to_string()); /// let address = "UCL CASA"; /// let bbox = InputBounds::new( @@ -583,54 +582,6 @@ where pub southwest: HashMap, } -/// Used to specify a bounding box to search within when forward-geocoding -/// -/// - `minimum` refers to the **bottom-left** or **south-west** corner of the bounding box -/// - `maximum` refers to the **top-right** or **north-east** corner of the bounding box. -#[derive(Copy, Clone, Debug)] -pub struct InputBounds -where - T: Float, -{ - pub minimum_lonlat: Point, - pub maximum_lonlat: Point, -} - -impl InputBounds -where - T: Float, -{ - /// Create a new `InputBounds` struct by passing 2 `Point`s defining: - /// - minimum (bottom-left) longitude and latitude coordinates - /// - maximum (top-right) longitude and latitude coordinates - pub fn new(minimum_lonlat: U, maximum_lonlat: U) -> InputBounds - where - U: Into>, - { - InputBounds { - minimum_lonlat: minimum_lonlat.into(), - maximum_lonlat: maximum_lonlat.into(), - } - } -} - -/// Convert borrowed input bounds into the correct String representation -impl From> for String -where - T: Float, -{ - fn from(ip: InputBounds) -> String { - // OpenCage expects lon, lat order here, for some reason - format!( - "{},{},{},{}", - ip.minimum_lonlat.x().to_f64().unwrap().to_string(), - ip.minimum_lonlat.y().to_f64().unwrap().to_string(), - ip.maximum_lonlat.x().to_f64().unwrap().to_string(), - ip.maximum_lonlat.y().to_f64().unwrap().to_string() - ) - } -} - #[cfg(test)] mod test { use super::*; diff --git a/src/openstreetmap.rs b/src/openstreetmap.rs index e31055b..701b1b4 100644 --- a/src/openstreetmap.rs +++ b/src/openstreetmap.rs @@ -17,6 +17,7 @@ //! assert_eq!(res.unwrap(), vec![Point::new(11.5761796, 48.1599218)]); //! ``` use crate::Deserialize; +use crate::InputBounds; use crate::Point; use crate::UA_STRING; use crate::{Client, HeaderMap, HeaderValue, USER_AGENT}; @@ -31,30 +32,35 @@ pub struct Openstreetmap { } /// An instance of a parameter builder for Openstreetmap geocoding -pub struct OpenstreetmapParams<'a> { +pub struct OpenstreetmapParams<'a, T> +where + T: Float, +{ query: &'a str, addressdetails: &'a bool, - viewbox: Option<&'a [f64; 4]>, + viewbox: Option<&'a InputBounds>, } -impl<'a> OpenstreetmapParams<'a> { +impl<'a, T> OpenstreetmapParams<'a, T> +where + T: Float, +{ /// Create a new OpenStreetMap parameter builder /// # Example: /// /// ``` - /// use geocoding::{Openstreetmap, OpenstreetmapParams, Point}; + /// use geocoding::{Openstreetmap, OpenstreetmapParams, InputBounds, Point}; /// + /// let viewbox = InputBounds::new( + /// (-0.13806939125061035, 51.51989264641164), + /// (-0.13427138328552246, 51.52319711775629), + /// ); /// let params = OpenstreetmapParams::new(&"UCL CASA") /// .with_addressdetails(&true) - /// .with_viewbox(&[ - /// -0.13806939125061035, - /// 51.51989264641164, - /// -0.13427138328552246, - /// 51.52319711775629, - /// ]) + /// .with_viewbox(&viewbox) /// .build(); /// ``` - pub fn new(query: &'a str) -> OpenstreetmapParams<'a> { + pub fn new(query: &'a str) -> OpenstreetmapParams<'a, T> { OpenstreetmapParams { query, addressdetails: &false, @@ -69,13 +75,13 @@ impl<'a> OpenstreetmapParams<'a> { } /// Set the `viewbox` property - pub fn with_viewbox(&mut self, viewbox: &'a [f64; 4]) -> &mut Self { + pub fn with_viewbox(&mut self, viewbox: &'a InputBounds) -> &mut Self { self.viewbox = Some(viewbox); self } /// Build and return an instance of OpenstreetmapParams - pub fn build(&self) -> OpenstreetmapParams<'a> { + pub fn build(&self) -> OpenstreetmapParams<'a, T> { OpenstreetmapParams { query: self.query, addressdetails: self.addressdetails, @@ -112,17 +118,16 @@ impl Openstreetmap { /// # Examples /// /// ``` - /// use geocoding::{Openstreetmap, OpenstreetmapParams, Point}; + /// use geocoding::{Openstreetmap, OpenstreetmapParams, InputBounds, Point}; /// /// let osm = Openstreetmap::new(); + /// let viewbox = InputBounds::new( + /// (-0.13806939125061035, 51.51989264641164), + /// (-0.13427138328552246, 51.52319711775629), + /// ); /// let params = OpenstreetmapParams::new(&"UCL CASA") /// .with_addressdetails(&true) - /// .with_viewbox(&[ - /// -0.13806939125061035, - /// 51.51989264641164, - /// -0.13427138328552246, - /// 51.52319711775629, - /// ]) + /// .with_viewbox(&viewbox) /// .build(); /// let res: OpenstreetmapResponse = osm.forward_full(¶ms).unwrap(); /// let result = res.features[0].properties.clone(); @@ -133,7 +138,7 @@ impl Openstreetmap { /// ``` pub fn forward_full( &self, - params: &OpenstreetmapParams, + params: &OpenstreetmapParams, ) -> Result, Error> where T: Float, @@ -151,11 +156,7 @@ impl Openstreetmap { ]; if let Some(vb) = params.viewbox { - viewbox = vb - .iter() - .map(|f| f.to_string()) - .collect::>() - .join(","); + viewbox = String::from(*vb); query.push((&"viewbox", &viewbox)); } @@ -340,14 +341,13 @@ mod test { #[test] fn forward_full_test() { let osm = Openstreetmap::new(); + let viewbox = InputBounds::new( + (-0.13806939125061035, 51.51989264641164), + (-0.13427138328552246, 51.52319711775629), + ); let params = OpenstreetmapParams::new(&"UCL CASA") .with_addressdetails(&true) - .with_viewbox(&[ - -0.13806939125061035, - 51.51989264641164, - -0.13427138328552246, - 51.52319711775629, - ]) + .with_viewbox(&viewbox) .build(); let res: OpenstreetmapResponse = osm.forward_full(¶ms).unwrap(); let result = res.features[0].properties.clone(); From d4cb6723519c74920440fe45bd506198061b4dbd Mon Sep 17 00:00:00 2001 From: pjsier Date: Mon, 19 Aug 2019 12:24:44 -0500 Subject: [PATCH 3/4] Add Openstreetmap new_with_endpoint constructor --- src/openstreetmap.rs | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/src/openstreetmap.rs b/src/openstreetmap.rs index 701b1b4..14e9211 100644 --- a/src/openstreetmap.rs +++ b/src/openstreetmap.rs @@ -91,8 +91,15 @@ where } impl Openstreetmap { - /// Create a new Openstreetmap geocoding instance + /// Create a new Openstreetmap geocoding instance using the default endpoint pub fn new() -> Self { + Openstreetmap::new_with_endpoint("https://nominatim.openstreetmap.org/".to_string()) + } + + /// Create a new Openstreetmap geocoding instance with a custom endpoint. + /// + /// Endpoint should include a trailing slash (i.e. "https://nominatim.openstreetmap.org/") + pub fn new_with_endpoint(endpoint: String) -> Self { let mut headers = HeaderMap::new(); headers.insert(USER_AGENT, HeaderValue::from_static(UA_STRING)); let client = Client::builder() @@ -101,7 +108,7 @@ impl Openstreetmap { .expect("Couldn't build a client!"); Openstreetmap { client, - endpoint: "https://nominatim.openstreetmap.org/".to_string(), + endpoint: endpoint.to_string(), } } @@ -338,6 +345,15 @@ where mod test { use super::*; + #[test] + fn new_with_endpoint_forward_test() { + let osm = + Openstreetmap::new_with_endpoint("https://nominatim.openstreetmap.org/".to_string()); + let address = "Schwabing, München"; + let res = osm.forward(&address); + assert_eq!(res.unwrap(), vec![Point::new(11.5761796, 48.1599218)]); + } + #[test] fn forward_full_test() { let osm = Openstreetmap::new(); From 5eb1dc3876ab773ca7785a7c00a98afe88acb63f Mon Sep 17 00:00:00 2001 From: pjsier Date: Mon, 19 Aug 2019 18:33:19 -0500 Subject: [PATCH 4/4] Fix doc tests, make struct fields public --- src/openstreetmap.rs | 60 +++++++++++++++++++++++--------------------- 1 file changed, 31 insertions(+), 29 deletions(-) diff --git a/src/openstreetmap.rs b/src/openstreetmap.rs index 14e9211..dd0e90f 100644 --- a/src/openstreetmap.rs +++ b/src/openstreetmap.rs @@ -13,7 +13,7 @@ //! //! let osm = Openstreetmap::new(); //! let address = "Schwabing, München"; -//! let res = oc.forward(&address); +//! let res = osm.forward(&address); //! assert_eq!(res.unwrap(), vec![Point::new(11.5761796, 48.1599218)]); //! ``` use crate::Deserialize; @@ -49,7 +49,8 @@ where /// # Example: /// /// ``` - /// use geocoding::{Openstreetmap, OpenstreetmapParams, InputBounds, Point}; + /// use geocoding::{Openstreetmap, InputBounds, Point}; + /// use geocoding::openstreetmap::{OpenstreetmapParams}; /// /// let viewbox = InputBounds::new( /// (-0.13806939125061035, 51.51989264641164), @@ -125,7 +126,8 @@ impl Openstreetmap { /// # Examples /// /// ``` - /// use geocoding::{Openstreetmap, OpenstreetmapParams, InputBounds, Point}; + /// use geocoding::{Openstreetmap, InputBounds, Point}; + /// use geocoding::openstreetmap::{OpenstreetmapParams, OpenstreetmapResponse}; /// /// let osm = Openstreetmap::new(); /// let viewbox = InputBounds::new( @@ -283,9 +285,9 @@ pub struct OpenstreetmapResponse where T: Float, { - r#type: String, - licence: String, - features: Vec>, + pub r#type: String, + pub licence: String, + pub features: Vec>, } /// A geocoding result @@ -303,32 +305,32 @@ where /// Geocoding result properties #[derive(Clone, Debug, Deserialize)] pub struct ResultProperties { - place_id: u64, - osm_type: String, - osm_id: u64, - display_name: String, - place_rank: u64, - category: String, - r#type: String, - importance: f64, - address: Option, + pub place_id: u64, + pub osm_type: String, + pub osm_id: u64, + pub display_name: String, + pub place_rank: u64, + pub category: String, + pub r#type: String, + pub importance: f64, + pub address: Option, } /// Address details in the result object #[derive(Clone, Debug, Deserialize)] pub struct AddressDetails { - city: Option, - city_district: Option, - construction: Option, - continent: Option, - country: Option, - country_code: Option, - house_number: Option, - neighbourhood: Option, - postcode: Option, - public_building: Option, - state: Option, - suburb: Option, + pub city: Option, + pub city_district: Option, + pub construction: Option, + pub continent: Option, + pub country: Option, + pub country_code: Option, + pub house_number: Option, + pub neighbourhood: Option, + pub postcode: Option, + pub public_building: Option, + pub state: Option, + pub suburb: Option, } /// A geocoding result geometry @@ -337,8 +339,8 @@ pub struct ResultGeometry where T: Float, { - r#type: String, - coordinates: (T, T), + pub r#type: String, + pub coordinates: (T, T), } #[cfg(test)]