egg_mode/place/
fun.rs

1// This Source Code Form is subject to the terms of the Mozilla Public
2// License, v. 2.0. If a copy of the MPL was not distributed with this
3// file, You can obtain one at http://mozilla.org/MPL/2.0/.
4
5use crate::common::*;
6use crate::error::{Error, Result};
7use crate::{auth, links};
8
9use super::PlaceQuery;
10use super::*;
11
12/// Load the place with the given ID.
13///
14/// ## Examples
15///
16/// ```rust,no_run
17/// # use egg_mode::Token;
18/// # #[tokio::main]
19/// # async fn main() {
20/// # let token: Token = unimplemented!();
21/// let result = egg_mode::place::show("18810aa5b43e76c7", &token).await.unwrap();
22///
23/// assert!(result.full_name == "Dallas, TX");
24/// # }
25/// ```
26pub async fn show(id: &str, token: &auth::Token) -> Result<Response<Place>> {
27    let url = format!("{}/{}.json", links::place::SHOW_STEM, id);
28    let req = get(&url, token, None);
29    request_with_json_response(req).await
30}
31
32/// Begins building a reverse-geocode search with the given coordinate.
33///
34/// ## Examples
35///
36/// ```rust,no_run
37/// # use egg_mode::Token;
38/// # #[tokio::main]
39/// # async fn main() {
40/// # let token: Token = unimplemented!();
41/// use egg_mode::place::{self, PlaceType};
42/// let result = place::reverse_geocode(51.507222, -0.1275)
43///     .granularity(PlaceType::City)
44///     .call(&token)
45///     .await
46///     .unwrap();
47///
48/// assert!(result.results.iter().any(|pl| pl.full_name == "London, England"));
49/// # }
50/// ```
51pub fn reverse_geocode(latitude: f64, longitude: f64) -> GeocodeBuilder {
52    GeocodeBuilder::new(latitude, longitude)
53}
54
55fn parse_url(base: &'static str, full: &str) -> Result<ParamList> {
56    let mut iter = full.split('?');
57
58    if let Some(base_part) = iter.next() {
59        if base_part != base {
60            return Err(Error::BadUrl);
61        }
62    } else {
63        return Err(Error::BadUrl);
64    }
65
66    if let Some(list) = iter.next() {
67        list.split('&').try_fold(ParamList::new(), |p, pair| {
68            let mut kv_iter = pair.split('=');
69            let k = kv_iter.next().ok_or(Error::BadUrl)?;
70            let v = kv_iter.next().ok_or(Error::BadUrl)?;
71            Ok(p.add_param(k.to_string(), v.to_string()))
72        })
73    } else {
74        Err(Error::BadUrl)
75    }
76}
77
78///From a URL given with the result of `reverse_geocode`, perform the same reverse-geocode search.
79///
80///## Errors
81///
82///In addition to errors that might occur generally, this function will return a `BadUrl` error if
83///the given URL is not a valid `reverse_geocode` query URL.
84pub async fn reverse_geocode_url(url: &str, token: &auth::Token) -> Result<Response<SearchResult>> {
85    let params = parse_url(links::place::REVERSE_GEOCODE, url)?;
86    let req = get(links::place::REVERSE_GEOCODE, token, Some(&params));
87    request_with_json_response(req).await
88}
89
90/// Begins building a location search via latitude/longitude.
91///
92/// ## Example
93///
94/// ```rust,no_run
95/// # use egg_mode::Token;
96/// # #[tokio::main]
97/// # async fn main() {
98/// # let token: Token = unimplemented!();
99/// use egg_mode::place::{self, PlaceType};
100/// let result = place::search_point(51.507222, -0.1275)
101///     .granularity(PlaceType::City)
102///     .call(&token)
103///     .await
104///     .unwrap();
105///
106/// assert!(result.results.iter().any(|pl| pl.full_name == "London, England"));
107/// # }
108/// ```
109pub fn search_point(latitude: f64, longitude: f64) -> SearchBuilder {
110    SearchBuilder::new(PlaceQuery::LatLon(latitude, longitude))
111}
112
113/// Begins building a location search via a text query.
114///
115/// ## Example
116///
117/// ```rust,no_run
118/// # use egg_mode::Token;
119/// # #[tokio::main]
120/// # async fn main() {
121/// # let token: Token = unimplemented!();
122/// use egg_mode::place::{self, PlaceType};
123/// let result = place::search_query("columbia")
124///     .granularity(PlaceType::Admin)
125///     .call(&token)
126///     .await
127///     .unwrap();
128///
129/// assert!(result.results.iter().any(|pl| pl.full_name == "British Columbia, Canada"));
130/// # }
131/// ```
132pub fn search_query(query: impl Into<CowStr>) -> SearchBuilder {
133    SearchBuilder::new(PlaceQuery::Query(query.into()))
134}
135
136///Begins building a location search via an IP address.
137pub fn search_ip(query: impl Into<CowStr>) -> SearchBuilder {
138    SearchBuilder::new(PlaceQuery::IPAddress(query.into()))
139}
140
141///From a URL given with the result of any `search_*` function, perform the same location search.
142///
143///## Errors
144///
145///In addition to errors that might occur generally, this function will return a `BadUrl` error if
146///the given URL is not a valid `search` query URL.
147pub async fn search_url(url: &str, token: &auth::Token) -> Result<Response<SearchResult>> {
148    let params = parse_url(links::place::SEARCH, url)?;
149    let req = get(links::place::REVERSE_GEOCODE, token, Some(&params));
150    request_with_json_response(req).await
151}