google_places_api/endpoints/
find_place.rs1use crate::types::constants::{Language, LocationBias, PlaceSearchPlace, PlaceSearchPlaceFields};
2use crate::types::FindPlaceSearchResult;
3use reqwest::Client;
4use std::collections::HashSet;
5
6pub struct FindPlace<'a> {
7 input: Option<String>,
8 input_type: Option<String>,
9 language: Option<Language>,
10 fields: Option<HashSet<PlaceSearchPlaceFields>>,
11 location_bias: Option<LocationBias>,
12 api_key: String,
13 client: &'a Client,
14 result: FindPlaceSearchResult,
15}
16
17impl<'a> FindPlace<'a> {
18 pub fn new(api_key: &str, client: &'a Client) -> Self {
29 Self {
30 input: None,
31 fields: None,
32 language: None,
33 location_bias: None,
34 input_type: None,
35 api_key: String::from(api_key),
36 client,
37 result: Default::default(),
38 }
39 }
40
41 pub fn with_input(&mut self, input: &str) -> &mut FindPlace<'a> {
47 self.input = Some(String::from(input));
48 self
49 }
50
51 pub fn with_fields(&mut self, fields: HashSet<PlaceSearchPlaceFields>) -> &mut FindPlace<'a> {
57 self.fields = Some(fields);
58 self
59 }
60
61 pub fn with_language(&mut self, language: Language) -> &mut FindPlace<'a> {
67 self.language = Some(language);
68 self
69 }
70
71 pub fn with_location_bias(&mut self, location_bias: LocationBias) -> &mut FindPlace<'a> {
77 self.location_bias = Some(location_bias);
78 self
79 }
80
81 pub fn with_input_type(&mut self, input_type: &str) -> &mut FindPlace<'a> {
87 self.input_type = Some(String::from(input_type));
88 self
89 }
90
91 fn build_params(&self) -> Vec<(&'static str, String)> {
92 let mut params = vec![("key", self.api_key.clone())];
93
94 if let Some(input) = &self.input {
95 params.push(("input", input.clone()));
96 }
97
98 if let Some(fields) = &self.fields {
99 params.push((
100 "fields",
101 fields
102 .iter()
103 .map(|f| f.to_string())
104 .collect::<Vec<_>>()
105 .join(","),
106 ));
107 }
108
109 if let Some(language) = &self.language {
110 params.push(("language", language.to_string()));
111 }
112
113 if let Some(location_bias) = &self.location_bias {
114 params.push(("locationbias", location_bias.to_string()));
115 }
116
117 if let Some(input_type) = &self.input_type {
118 params.push(("inputtype", input_type.clone()));
119 }
120
121 params
122 }
123
124 pub async fn execute(&mut self) -> Option<&mut FindPlace<'a>> {
128 match (self.input.clone(), self.input_type.clone()) {
129 (Some(_), Some(_)) => {
130 let url = "https://maps.googleapis.com/maps/api/place/findplacefromtext/json";
131 let params = self.build_params();
132
133 let resp = self.client.get(url).query(¶ms).send().await.unwrap();
134
135 match resp.json::<FindPlaceSearchResult>().await {
136 Ok(query_result) => {
137 self.result = query_result;
138 Some(self)
139 }
140 Err(err) => {
141 println!("Error parsing response: {:?}", err);
142
143 None
144 }
145 }
146 }
147
148 _ => {panic!("Provide input and inputtype for find_place query!");}
149 }
150 }
151
152 #[cfg(feature = "blocking")]
156 pub fn execute_blocking(&mut self) -> Option<&mut FindPlace<'a>> {
157 tokio::runtime::Runtime::new()
158 .unwrap()
159 .block_on(self.execute())
160 }
161
162 pub fn iter(&mut self) -> FindPlaceIterator<'_, 'a> {
170 FindPlaceIterator {
171 find_place: self,
172 current_index: 0,
173 }
174 }
175
176 pub fn at(&self, index: usize) -> Option<&PlaceSearchPlace> {
184 self.result.places.get(index)
185 }
186 pub fn get_result(&self) -> FindPlaceSearchResult {
187 self.result.clone()
188 }
189}
190
191pub struct FindPlaceIterator<'a, 'b> {
201 find_place: &'b mut FindPlace<'a>,
202 current_index: usize,
203}
204
205impl<'a, 'b> Iterator for FindPlaceIterator<'a, 'b> {
206 type Item = &'b PlaceSearchPlace;
207
208 fn next(&mut self) -> Option<Self::Item> {
218 if self.current_index < self.find_place.result.places.len() {
219 let place = &self.find_place.result.places[self.current_index];
220 self.current_index += 1;
221 Some(unsafe { std::mem::transmute(place) })
222 } else {
223 None
224 }
225 }
226}