1#![allow(clippy::field_reassign_with_default)]
25use std::env;
26use std::error;
27use std::fmt::{self, Debug, Display, Formatter};
28use std::hash::Hash;
29use std::sync::Arc;
30
31use reqwest::{header, Client, Method, Request, StatusCode, Url};
32use serde::{Deserialize, Serialize};
33
34const ENDPOINT: &str = "https://maps.google.com/maps/api/geocode/json";
36
37pub struct Geocode {
39 key: String,
40
41 client: Arc<Client>,
42}
43
44impl Geocode {
45 pub fn new<K>(key: K) -> Self
49 where
50 K: ToString,
51 {
52 let client = Client::builder().build();
53 match client {
54 Ok(c) => Self {
55 key: key.to_string(),
56
57 client: Arc::new(c),
58 },
59 Err(e) => panic!("creating client failed: {:?}", e),
60 }
61 }
62
63 pub fn new_from_env() -> Self {
68 let key = env::var("GOOGLE_GEOCODE_API_KEY").unwrap();
69
70 Geocode::new(key)
71 }
72
73 fn request<B>(&self, method: Method, path: &str, body: B, query: Option<Vec<(&str, String)>>) -> Request
74 where
75 B: Serialize,
76 {
77 let base = Url::parse(ENDPOINT).unwrap();
78 let url = base.join(path).unwrap();
79
80 let mut headers = header::HeaderMap::new();
82 headers.append(header::CONTENT_TYPE, header::HeaderValue::from_static("application/json"));
83
84 let mut rb = self.client.request(method.clone(), url).headers(headers).basic_auth(&self.key, Some(""));
85
86 match query {
87 None => (),
88 Some(val) => {
89 rb = rb.query(&val);
90 }
91 }
92
93 if method != Method::GET && method != Method::DELETE {
95 rb = rb.json(&body);
96 }
97
98 rb.build().unwrap()
100 }
101
102 pub async fn get(&self, address: &str) -> Result<Reply, APIError> {
104 let request = self.request(Method::GET, "", (), Some(vec![("address", address.to_string()), ("key", self.key.to_string())]));
106
107 let resp = self.client.execute(request).await.unwrap();
108 match resp.status() {
109 StatusCode::OK => (),
110 s => {
111 return Err(APIError {
112 status_code: s,
113 body: resp.text().await.unwrap(),
114 })
115 }
116 };
117
118 let r: ReplyResult = resp.json().await.unwrap();
119 if r.results.is_empty() {
120 return Err(APIError {
121 status_code: StatusCode::NOT_FOUND,
122 body: "".to_string(),
123 });
124 }
125 Ok(r.results.get(0).unwrap().clone())
126 }
127}
128
129pub struct APIError {
131 pub status_code: StatusCode,
132 pub body: String,
133}
134
135impl fmt::Display for APIError {
136 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
137 write!(f, "APIError: status code -> {}, body -> {}", self.status_code.to_string(), self.body)
138 }
139}
140
141impl fmt::Debug for APIError {
142 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
143 write!(f, "APIError: status code -> {}, body -> {}", self.status_code.to_string(), self.body)
144 }
145}
146
147impl error::Error for APIError {
149 fn source(&self) -> Option<&(dyn error::Error + 'static)> {
150 None
152 }
153}
154
155#[derive(Debug, Clone, Deserialize, Serialize)]
157pub struct AddressComponent {
158 #[serde(default)]
160 long_name: String,
161 #[serde(default)]
164 short_name: String,
165 #[serde(default)]
167 types: Vec<String>,
168}
169
170#[derive(Debug, Clone, Deserialize)]
172pub struct Geometry {
173 pub location: Coordinates,
176 pub location_type: LocationType,
178 pub viewport: Viewport,
180 pub bounds: Option<Viewport>,
183}
184
185#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
187#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
188pub enum LocationType {
189 Rooftop,
192
193 RangeInterpolated,
198
199 GeometricCenter,
202
203 Approximate,
205}
206
207#[derive(Debug, Clone, Deserialize)]
209pub struct FormattedAddress(String);
210
211impl Display for FormattedAddress {
212 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
213 Display::fmt(&self.0, f)
214 }
215}
216
217#[derive(Debug, Default, Deserialize)]
218struct ReplyResult {
219 #[serde(default)]
220 error_message: String,
221 #[serde(default)]
222 results: Vec<Reply>,
223 #[serde(default)]
224 status: String,
225}
226
227#[derive(Debug, Clone, Deserialize)]
229pub struct Reply {
230 #[serde(default)]
232 pub address_components: Vec<AddressComponent>,
233 pub formatted_address: FormattedAddress,
241 pub geometry: Geometry,
243 pub place_id: PlaceId,
245 #[serde(default)]
248 pub postcode_localities: Vec<String>,
249
250 #[serde(default)]
252 pub types: Vec<String>,
253}
254
255#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
256pub struct Viewport {
257 pub northeast: Coordinates,
259 pub southwest: Coordinates,
261}
262
263#[derive(Clone, Copy, Debug, Serialize)]
267#[allow(dead_code)]
268pub enum Language {
269 #[serde(rename = "ar")]
271 Arabic,
272 #[serde(rename = "bg")]
274 Bulgarian,
275 #[serde(rename = "bn")]
277 Bengali,
278 #[serde(rename = "ca")]
280 Catalan,
281 #[serde(rename = "cs")]
283 Czech,
284 #[serde(rename = "da")]
286 Danish,
287 #[serde(rename = "de")]
289 German,
290 #[serde(rename = "el")]
292 Greek,
293 #[serde(rename = "en")]
295 English,
296 #[serde(rename = "en-AU")]
298 EnglishAustralian,
299 #[serde(rename = "en-GB")]
301 EnglishGreatBritain,
302 #[serde(rename = "es")]
304 Spanish,
305 #[serde(rename = "eu")]
307 Basque,
308 #[serde(rename = "fa")]
310 Farsi,
311 #[serde(rename = "fi")]
313 Finnish,
314 #[serde(rename = "fil")]
316 Filipino,
317 #[serde(rename = "fr")]
319 French,
320 #[serde(rename = "gl")]
322 Galician,
323 #[serde(rename = "gu")]
325 Gujarati,
326 #[serde(rename = "hi")]
328 Hindi,
329 #[serde(rename = "hr")]
331 Croatian,
332 #[serde(rename = "hu")]
334 Hungarian,
335 #[serde(rename = "id")]
337 Indonesian,
338 #[serde(rename = "it")]
340 Italian,
341 #[serde(rename = "iw")]
343 Hebrew,
344 #[serde(rename = "ja")]
346 Japanese,
347 #[serde(rename = "kn")]
349 Kannada,
350 #[serde(rename = "ko")]
352 Korean,
353 #[serde(rename = "lt")]
355 Lithuanian,
356 #[serde(rename = "lv")]
358 Latvian,
359 #[serde(rename = "ml")]
361 Malayalam,
362 #[serde(rename = "mr")]
364 Marathi,
365 #[serde(rename = "nl")]
367 Dutch,
368 #[serde(rename = "no")]
370 Norwegian,
371 #[serde(rename = "pl")]
373 Polish,
374 #[serde(rename = "pt")]
376 Portuguese,
377 #[serde(rename = "pt-BR")]
379 PortugueseBrazil,
380 #[serde(rename = "pt-PT")]
382 PortuguesePortugal,
383 #[serde(rename = "ro")]
385 Romanian,
386 #[serde(rename = "ru")]
388 Russian,
389 #[serde(rename = "sk")]
391 Slovak,
392 #[serde(rename = "sl")]
394 Slovenian,
395 #[serde(rename = "sr")]
397 Serbian,
398 #[serde(rename = "sv")]
400 Swedish,
401 #[serde(rename = "ta")]
403 Tamil,
404 #[serde(rename = "te")]
406 Telugu,
407 #[serde(rename = "th")]
409 Thai,
410 #[serde(rename = "tl")]
412 Tagalog,
413 #[serde(rename = "tr")]
415 Turkish,
416 #[serde(rename = "uk")]
418 Ukrainian,
419 #[serde(rename = "vi")]
421 Vietnamese,
422 #[serde(rename = "zh-CN")]
424 ChineseSimplified,
425 #[serde(rename = "zh-TW")]
427 ChineseTraditional,
428}
429
430#[derive(Clone, Copy, Debug, Serialize)]
433#[allow(dead_code)]
434pub enum Region {
435 #[serde(rename = ".ac")]
437 AscensionIsland,
438 #[serde(rename = ".ad")]
440 Andorra,
441 #[serde(rename = ".ae")]
443 UnitedArabEmirates,
444 #[serde(rename = ".af")]
446 Afghanistan,
447 #[serde(rename = ".ag")]
449 AntiguaAndBarbuda,
450 #[serde(rename = ".ai")]
452 Anguilla,
453 #[serde(rename = ".al")]
455 Albania,
456 #[serde(rename = ".am")]
458 Armenia,
459 #[serde(rename = ".an")]
461 AntillesNetherlands,
462 #[serde(rename = ".ao")]
464 Angola,
465 #[serde(rename = ".aq")]
467 Antarctica,
468 #[serde(rename = ".ar")]
470 Argentina,
471 #[serde(rename = ".as")]
473 AmericanSamoa,
474 #[serde(rename = ".at")]
476 Austria,
477 #[serde(rename = ".au")]
479 Australia,
480 #[serde(rename = ".aw")]
482 Aruba,
483 #[serde(rename = ".ax")]
485 AlandIslands,
486 #[serde(rename = ".az")]
488 Azerbaijan,
489 #[serde(rename = ".ba")]
491 BosniaAndHerzegovina,
492 #[serde(rename = ".bb")]
494 Barbados,
495 #[serde(rename = ".bd")]
497 Bangladesh,
498 #[serde(rename = ".be")]
500 Belgium,
501 #[serde(rename = ".bf")]
503 BurkinaFaso,
504 #[serde(rename = ".bg")]
506 Bulgaria,
507 #[serde(rename = ".bh")]
509 Bahrain,
510 #[serde(rename = ".bi")]
512 Burundi,
513 #[serde(rename = ".bj")]
515 Benin,
516 #[serde(rename = ".bl")]
518 SaintBarthelemy,
519 #[serde(rename = ".bm")]
521 Bermuda,
522 #[serde(rename = ".bn")]
524 BruneiDarussalam,
525 #[serde(rename = ".bo")]
527 Bolivia,
528 #[serde(rename = ".bq")]
530 BonaireSintEustatiusAndSaba,
531 #[serde(rename = ".br")]
533 Brazil,
534 #[serde(rename = ".bs")]
536 Bahamas,
537 #[serde(rename = ".bt")]
539 Bhutan,
540 #[serde(rename = ".bv")]
542 BouvetIsland,
543 #[serde(rename = ".bw")]
545 Botswana,
546 #[serde(rename = ".by")]
548 Belarus,
549 #[serde(rename = ".bz")]
551 Belize,
552 #[serde(rename = ".ca")]
554 Canada,
555 #[serde(rename = ".cc")]
557 CocosIslands,
558 #[serde(rename = ".cd")]
560 DemocraticRepublicOfTheCongo,
561 #[serde(rename = ".cf")]
563 CentralAfricanRepublic,
564 #[serde(rename = ".cg")]
566 RepublicOfCongo,
567 #[serde(rename = ".ch")]
569 Switzerland,
570 #[serde(rename = ".ci")]
572 CoteDivoire,
573 #[serde(rename = ".ck")]
575 CookIslands,
576 #[serde(rename = ".cl")]
578 Chile,
579 #[serde(rename = ".cm")]
581 Cameroon,
582 #[serde(rename = ".cn")]
584 China,
585 #[serde(rename = ".co")]
587 Colombia,
588 #[serde(rename = ".cr")]
590 CostaRica,
591 #[serde(rename = ".cu")]
593 Cuba,
594 #[serde(rename = ".cv")]
596 CapeVerde,
597 #[serde(rename = ".cw")]
599 Curacao,
600 #[serde(rename = ".cx")]
602 ChristmasIsland,
603 #[serde(rename = ".cy")]
605 Cyprus,
606 #[serde(rename = ".cz")]
608 CzechRepublic,
609 #[serde(rename = ".de")]
611 Germany,
612 #[serde(rename = ".dj")]
614 Djibouti,
615 #[serde(rename = ".dk")]
617 Denmark,
618 #[serde(rename = ".dm")]
620 Dominica,
621 #[serde(rename = ".do")]
623 DominicanRepublic,
624 #[serde(rename = ".dz")]
626 Algeria,
627 #[serde(rename = ".ec")]
629 Ecuador,
630 #[serde(rename = ".ee")]
632 Estonia,
633 #[serde(rename = ".eg")]
635 Egypt,
636 #[serde(rename = ".eh")]
638 WesternSahara,
639 #[serde(rename = ".er")]
641 Eritrea,
642 #[serde(rename = ".es")]
644 Spain,
645 #[serde(rename = ".et")]
647 Ethiopia,
648 #[serde(rename = ".eu")]
650 EuropeanUnion,
651 #[serde(rename = ".fi")]
653 Finland,
654 #[serde(rename = ".fj")]
656 Fiji,
657 #[serde(rename = ".fk")]
659 FalklandIslands,
660 #[serde(rename = ".fm")]
662 FederatedStatesOfMicronesia,
663 #[serde(rename = ".fo")]
665 FaroeIslands,
666 #[serde(rename = ".fr")]
668 France,
669 #[serde(rename = ".ga")]
671 Gabon,
672 #[serde(rename = ".gd")]
674 Grenada,
675 #[serde(rename = ".ge")]
677 Georgia,
678 #[serde(rename = ".gf")]
680 FrenchGuiana,
681 #[serde(rename = ".gg")]
683 Guernsey,
684 #[serde(rename = ".gh")]
686 Ghana,
687 #[serde(rename = ".gi")]
689 Gibraltar,
690 #[serde(rename = ".gl")]
692 Greenland,
693 #[serde(rename = ".gm")]
695 Gambia,
696 #[serde(rename = ".gn")]
698 Guinea,
699 #[serde(rename = ".gp")]
701 Guadeloupe,
702 #[serde(rename = ".gq")]
704 EquatorialGuinea,
705 #[serde(rename = ".gr")]
707 Greece,
708 #[serde(rename = ".gs")]
710 SouthGeorgiaAndTheSouthSandwichIslands,
711 #[serde(rename = ".gt")]
713 Guatemala,
714 #[serde(rename = ".gu")]
716 Guam,
717 #[serde(rename = ".gw")]
719 GuineaBissau,
720 #[serde(rename = ".gy")]
722 Guyana,
723 #[serde(rename = ".hk")]
725 HongKong,
726 #[serde(rename = ".hm")]
728 HeardIslandAndMcDonaldIslands,
729 #[serde(rename = ".hn")]
731 Honduras,
732 #[serde(rename = ".hr")]
734 Croatia,
735 #[serde(rename = ".ht")]
737 Haiti,
738 #[serde(rename = ".hu")]
740 Hungary,
741 #[serde(rename = ".id")]
743 Indonesia,
744 #[serde(rename = ".ie")]
746 Ireland,
747 #[serde(rename = ".il")]
749 Israel,
750 #[serde(rename = ".im")]
752 IsleOfMan,
753 #[serde(rename = ".in")]
755 India,
756 #[serde(rename = ".io")]
758 BritishIndianOceanTerritory,
759 #[serde(rename = ".iq")]
761 Iraq,
762 #[serde(rename = ".ir")]
764 IslamicRepublicOfIran,
765 #[serde(rename = ".is")]
767 Iceland,
768 #[serde(rename = ".it")]
770 Italy,
771 #[serde(rename = ".je")]
773 Jersey,
774 #[serde(rename = ".jm")]
776 Jamaica,
777 #[serde(rename = ".jo")]
779 Jordan,
780 #[serde(rename = ".jp")]
782 Japan,
783 #[serde(rename = ".ke")]
785 Kenya,
786 #[serde(rename = ".kg")]
788 Kyrgyzstan,
789 #[serde(rename = ".kh")]
791 Cambodia,
792 #[serde(rename = ".ki")]
794 Kiribati,
795 #[serde(rename = ".km")]
797 Comoros,
798 #[serde(rename = ".kn")]
800 SaintKittsAndNevis,
801 #[serde(rename = ".kp")]
803 DemocraticPeoplesRepublicOfKorea,
804 #[serde(rename = ".kp")]
806 RepublicOfKorea,
807 #[serde(rename = ".kw")]
809 Kuwait,
810 #[serde(rename = ".ky")]
812 CaymenIslands,
813 #[serde(rename = ".kz")]
815 Kazakhstan,
816 #[serde(rename = ".la")]
818 Laos,
819 #[serde(rename = ".lb")]
821 Lebanon,
822 #[serde(rename = ".lc")]
824 SaintLucia,
825 #[serde(rename = ".li")]
827 Liechtenstein,
828 #[serde(rename = ".lk")]
830 SriLanka,
831 #[serde(rename = ".lr")]
833 Liberia,
834 #[serde(rename = ".ls")]
836 Lesotho,
837 #[serde(rename = ".lt")]
839 Lithuania,
840 #[serde(rename = ".lu")]
842 Luxembourg,
843 #[serde(rename = ".lv")]
845 Latvia,
846 #[serde(rename = ".ly")]
848 Libya,
849 #[serde(rename = ".ma")]
851 Morocco,
852 #[serde(rename = ".mc")]
854 Monaco,
855 #[serde(rename = ".md")]
857 RepublicOfMoldova,
858 #[serde(rename = ".me")]
860 Montenegro,
861 #[serde(rename = ".mf")]
863 SaintMartin,
864 #[serde(rename = ".mg")]
866 Madagascar,
867 #[serde(rename = ".mh")]
869 MarshallIslands,
870 #[serde(rename = ".mk")]
872 Macedonia,
873 #[serde(rename = ".ml")]
875 Mali,
876 #[serde(rename = ".mm")]
878 Myanmar,
879 #[serde(rename = ".mn")]
881 Mongolia,
882 #[serde(rename = ".mo")]
884 Macao,
885 #[serde(rename = ".mp")]
887 NorthernMarianaIslands,
888 #[serde(rename = ".mq")]
890 Martinique,
891 #[serde(rename = ".mr")]
893 Mauritania,
894 #[serde(rename = ".ms")]
896 Montserrat,
897 #[serde(rename = ".mt")]
899 Malta,
900 #[serde(rename = ".mu")]
902 Mauritius,
903 #[serde(rename = ".mv")]
905 Maldives,
906 #[serde(rename = ".mw")]
908 Malawi,
909 #[serde(rename = ".mx")]
911 Mexico,
912 #[serde(rename = ".my")]
914 Malaysia,
915 #[serde(rename = ".mz")]
917 Mozambique,
918 #[serde(rename = ".na")]
920 Namibia,
921 #[serde(rename = ".nc")]
923 NewCaledonia,
924 #[serde(rename = ".ne")]
926 Niger,
927 #[serde(rename = ".nf")]
929 NorfolkIsland,
930 #[serde(rename = ".ng")]
932 Nigeria,
933 #[serde(rename = ".ni")]
935 Nicaragua,
936 #[serde(rename = ".nl")]
938 Netherlands,
939 #[serde(rename = ".no")]
941 Norway,
942 #[serde(rename = ".np")]
944 Nepal,
945 #[serde(rename = ".nr")]
947 Nauru,
948 #[serde(rename = ".nu")]
950 Niue,
951 #[serde(rename = ".nz")]
953 NewZealand,
954 #[serde(rename = ".om")]
956 Oman,
957 #[serde(rename = ".pa")]
959 Panama,
960 #[serde(rename = ".pe")]
962 Peru,
963 #[serde(rename = ".pf")]
965 FrenchPolynesia,
966 #[serde(rename = ".pg")]
968 PapuaNewGuinea,
969 #[serde(rename = ".ph")]
971 Philippines,
972 #[serde(rename = ".pk")]
974 Pakistan,
975 #[serde(rename = ".pl")]
977 Poland,
978 #[serde(rename = ".pm")]
980 SaintPierreAndMiquelon,
981 #[serde(rename = ".pn")]
983 Pitcairn,
984 #[serde(rename = ".pr")]
986 PuertoRico,
987 #[serde(rename = ".ps")]
989 Palestine,
990 #[serde(rename = ".pt")]
992 Portugal,
993 #[serde(rename = ".pw")]
995 Palau,
996 #[serde(rename = ".py")]
998 Paraguay,
999 #[serde(rename = ".qa")]
1001 Qatar,
1002 #[serde(rename = ".re")]
1004 Reunion,
1005 #[serde(rename = ".ro")]
1007 Romania,
1008 #[serde(rename = ".rs")]
1010 Serbia,
1011 #[serde(rename = ".ru")]
1013 Russia,
1014 #[serde(rename = ".rw")]
1016 Rwanda,
1017 #[serde(rename = ".sa")]
1019 SaudiArabia,
1020 #[serde(rename = ".sb")]
1022 SolomonIslands,
1023 #[serde(rename = ".sc")]
1025 Seychelles,
1026 #[serde(rename = ".sd")]
1028 Sudan,
1029 #[serde(rename = ".se")]
1031 Sweden,
1032 #[serde(rename = ".sg")]
1034 Singapore,
1035 #[serde(rename = ".sh")]
1037 SaintHelena,
1038 #[serde(rename = ".si")]
1040 Slovenia,
1041 #[serde(rename = ".sj")]
1043 SvalbardAndJanMayen,
1044 #[serde(rename = ".sk")]
1046 Slovakia,
1047 #[serde(rename = ".sl")]
1049 SierraLeone,
1050 #[serde(rename = ".sm")]
1052 SanMarino,
1053 #[serde(rename = ".sn")]
1055 Senegal,
1056 #[serde(rename = ".so")]
1058 Somalia,
1059 #[serde(rename = ".sr")]
1061 Suriname,
1062 #[serde(rename = ".ss")]
1064 SouthSudan,
1065 #[serde(rename = ".st")]
1067 SaoTomeAndPrincipe,
1068 #[serde(rename = ".su")]
1070 SovietUnion,
1071 #[serde(rename = ".sv")]
1073 ElSalvador,
1074 #[serde(rename = ".sx")]
1076 SintMaarten,
1077 #[serde(rename = ".sy")]
1079 Syria,
1080 #[serde(rename = ".sz")]
1082 Swaziland,
1083 #[serde(rename = ".tc")]
1085 TurksAndCaicosIslands,
1086 #[serde(rename = ".td")]
1088 Chad,
1089 #[serde(rename = ".tf")]
1091 FrenchSouthernTerritories,
1092 #[serde(rename = ".tg")]
1094 Togo,
1095 #[serde(rename = ".th")]
1097 Thailand,
1098 #[serde(rename = ".tj")]
1100 Tajikistan,
1101 #[serde(rename = ".tk")]
1103 Tokelau,
1104 #[serde(rename = ".tl")]
1106 TimorLeste,
1107 #[serde(rename = ".tm")]
1109 Turkmenistan,
1110 #[serde(rename = ".tn")]
1112 Tunisia,
1113 #[serde(rename = ".to")]
1115 Tonga,
1116 #[serde(rename = ".tp")]
1118 PortugueseTimor,
1119 #[serde(rename = ".tr")]
1121 Turkey,
1122 #[serde(rename = ".tt")]
1124 TrinidadAndTobago,
1125 #[serde(rename = ".tv")]
1127 Tuvalu,
1128 #[serde(rename = ".tw")]
1130 Taiwan,
1131 #[serde(rename = ".tz")]
1133 Tanzania,
1134 #[serde(rename = ".ua")]
1136 Ukraine,
1137 #[serde(rename = ".ug")]
1139 Uganda,
1140 #[serde(rename = ".uk")]
1142 UnitedKingdom,
1143 #[serde(rename = ".um")]
1145 UnitedStatesMinorOutlyingIslands,
1146 #[serde(rename = ".us")]
1148 UnitedStates,
1149 #[serde(rename = ".uy")]
1151 Uruguay,
1152 #[serde(rename = ".uz")]
1154 Uzbekistan,
1155 #[serde(rename = ".va")]
1157 VaticanCity,
1158 #[serde(rename = ".vc")]
1160 SaintVincentAndTheGrenadines,
1161 #[serde(rename = ".ve")]
1163 Venezuela,
1164 #[serde(rename = ".vg")]
1166 BritishVirginIslands,
1167 #[serde(rename = ".vi")]
1169 USVirginIslands,
1170 #[serde(rename = ".vn")]
1172 Vietnam,
1173 #[serde(rename = ".vu")]
1175 Vanuatu,
1176 #[serde(rename = ".wf")]
1178 WallisAndFutuna,
1179 #[serde(rename = ".ws")]
1181 Samoa,
1182 #[serde(rename = ".yt")]
1184 Mayote,
1185 #[serde(rename = ".za")]
1187 SouthAfrica,
1188 #[serde(rename = ".zm")]
1190 Zambia,
1191 #[serde(rename = ".zw")]
1193 Zimbabwe,
1194}
1195
1196#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
1198pub struct Coordinates {
1199 pub lat: f64,
1200 pub lng: f64,
1201}
1202
1203#[derive(Debug, Clone, Deserialize, Eq, Hash, PartialEq, Serialize)]
1206pub struct PlaceId(String);