mapsco_client/
lib.rs

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}