Skip to main content

pysochrone/
geocoding.rs

1use crate::error::OsmGraphError;
2use crate::overpass::CLIENT;
3use serde::Deserialize;
4
5#[derive(Deserialize)]
6struct NominatimResult {
7    lat: String,
8    lon: String,
9}
10
11/// Geocode a place name to (lat, lon) using the Nominatim API.
12/// Nominatim usage policy requires a descriptive User-Agent and max 1 req/sec.
13pub async fn geocode(place: &str) -> Result<(f64, f64), OsmGraphError> {
14    let response = CLIENT
15        .get("https://nominatim.openstreetmap.org/search")
16        .query(&[("q", place), ("format", "json"), ("limit", "1")])
17        .header("User-Agent", "osm_graph/0.1 (https://github.com/kyleloving/osm_graph)")
18        .send()
19        .await?;
20
21    let results: Vec<NominatimResult> = response.json().await?;
22
23    let first = results.into_iter().next()
24        .ok_or_else(|| OsmGraphError::GeocodingFailed(place.to_string()))?;
25
26    let lat = first.lat.parse::<f64>()
27        .map_err(|_| OsmGraphError::GeocodingFailed(place.to_string()))?;
28    let lon = first.lon.parse::<f64>()
29        .map_err(|_| OsmGraphError::GeocodingFailed(place.to_string()))?;
30
31    Ok((lat, lon))
32}