1use serde::{Deserialize, Serialize};
2use serde_this_or_that::as_f64;
3#[derive(Serialize, Deserialize, Debug, Clone)]
4pub struct LocationData {
5 pub place_id: i64,
6 pub licence: Option<String>,
7 pub osm_type: Option<String>,
8 pub osm_id: Option<i64>,
9 #[serde(deserialize_with = "as_f64")]
10 pub lat: f64,
11 #[serde(deserialize_with = "as_f64")]
12 pub lon: f64,
13 pub display_name: String,
14 pub address: Option<Address>,
15 pub boundingbox: Vec<String>,
16 pub class: Option<String>,
17 pub r#type: Option<String>,
18 pub importance: Option<f64>,
19}
20use std::fmt;
21impl fmt::Display for LocationData {
22 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
23 write!(f, "{}", &self.display_name)
24 }
25}
26
27#[derive(Serialize, Deserialize, Debug, Clone)]
28pub struct Address {
29 pub house_number: Option<String>,
30 pub road: Option<String>,
31 pub suburb: Option<String>,
32 pub city: Option<String>,
33 pub town: Option<String>,
34 pub village: Option<String>,
35 pub county: Option<String>,
36 pub state: Option<String>,
37 #[serde(rename = "ISO3166-2-lvl4")]
38 pub iso3166_2_lvl4: Option<String>,
39 pub postcode: Option<String>,
40 pub country: Option<String>,
41 pub country_code: Option<String>,
42}
43
44#[derive(Clone)]
45#[cfg(feature = "reqwest")]
46pub struct MapscoClient {
47 client: reqwest::Client,
48 base_url: String,
49 api_key: String,
50}
51#[cfg(feature = "reqwest")]
52extern crate reqwest;
53#[cfg(feature = "reqwest")]
54impl MapscoClient {
55 pub fn new_from_env() -> Self {
56 Self::new(
57 std::env::var("MAPSCO_API_KEY")
58 .expect("MAPSCO_API_KEY must be set")
59 .to_string(),
60 )
61 }
62 pub fn new(api_key: String) -> Self {
63 Self {
64 api_key,
65 client: reqwest::Client::new(),
66 base_url: "https://geocode.maps.co".into(),
67 }
68 }
69
70 pub async fn reverse(&self, lat: f64, lon: f64) -> Result<LocationData, reqwest::Error> {
71 let response = self
72 .client
73 .get(
74 reqwest::Url::parse_with_params(
75 &format!("{}/reverse", self.base_url),
76 &[
77 ("lat", lat.to_string()),
78 ("lon", lon.to_string()),
79 ("api_key", self.api_key.clone()),
80 ],
81 )
82 .unwrap(),
83 )
84 .send()
85 .await?;
86
87 let text = response.text().await?;
88 println!("{:?}", text);
89 Ok(serde_json::from_str::<LocationData>(text.as_str()).unwrap())
90 }
91
92 pub async fn search(&self, query: &str) -> anyhow::Result<Vec<LocationData>> {
93 let response = self
94 .client
95 .get(
96 reqwest::Url::parse_with_params(
97 &format!("{}/search", self.base_url),
98 &[("q", query.to_string()), ("api_key", self.api_key.clone())],
99 )
100 .unwrap(),
101 )
102 .send()
103 .await?;
104 let text = response.text().await?;
105 Ok(serde_json::from_str::<Vec<LocationData>>(text.as_str())?)
106 }
107}