use std::str::FromStr; use rocket::{get, serde::json::Json, Responder}; use serde::{Deserialize, Serialize}; use xpin::Address; #[get("/address?&")] pub(crate) fn get_address(lat: Option, lon: Option) -> Result { let (lat, lon) = lat.zip(lon).ok_or(ApiError::InvalidRequest( "lat and lon parameters are required", ))?; let lat = lat .parse::() .map_err(|_| ApiError::InvalidRequest("Invalid lat parameter"))?; let lon = lon .parse::() .map_err(|_| ApiError::InvalidRequest("Invalid lon parameter"))?; Ok(Address::from_lat_lon(lat, lon)?.to_string()) } #[get("/coords?
")] pub(crate) fn get_coords(address: Option) -> Result, ApiError> { let address = address.ok_or(ApiError::InvalidRequest("address parameter required"))?; Address::from_str(&address) .as_ref() .map_err(Into::into) .map(Address::as_lat_lon) .map(Coords::from) .map(Json) } #[derive(Serialize, Deserialize)] pub(crate) struct Coords { lat: f64, lon: f64, } impl From<(f64, f64)> for Coords { fn from((lat, lon): (f64, f64)) -> Self { Self { lat, lon } } } #[derive(Responder)] #[response(status = 400)] pub(crate) enum ApiError { #[response(status = 400)] AlgorithmError(String), #[response(status = 400)] InvalidRequest(&'static str), } impl From<&xpin::Error> for ApiError { fn from(e: &xpin::Error) -> Self { Self::AlgorithmError(e.to_string()) } } impl From for ApiError { fn from(e: xpin::Error) -> Self { Self::from(&e) } }