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(¶ms));
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(¶ms));
150 request_with_json_response(req).await
151}