66 lines
1.6 KiB
Rust
66 lines
1.6 KiB
Rust
use std::str::FromStr;
|
|
|
|
use rocket::{get, serde::json::Json, Responder};
|
|
use serde::{Deserialize, Serialize};
|
|
use xpin::Address;
|
|
|
|
#[get("/address?<lat>&<lon>")]
|
|
pub(crate) fn get_address(lat: Option<String>, lon: Option<String>) -> Result<String, ApiError> {
|
|
let (lat, lon) = lat.zip(lon).ok_or(ApiError::InvalidRequest(
|
|
"lat and lon parameters are required",
|
|
))?;
|
|
let lat = lat
|
|
.parse::<f64>()
|
|
.map_err(|_| ApiError::InvalidRequest("Invalid lat parameter"))?;
|
|
let lon = lon
|
|
.parse::<f64>()
|
|
.map_err(|_| ApiError::InvalidRequest("Invalid lon parameter"))?;
|
|
|
|
Ok(Address::from_lat_lon(lat, lon)?.to_string())
|
|
}
|
|
|
|
#[get("/coords?<address>")]
|
|
pub(crate) fn get_coords(address: Option<String>) -> Result<Json<Coords>, 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<xpin::Error> for ApiError {
|
|
fn from(e: xpin::Error) -> Self {
|
|
Self::from(&e)
|
|
}
|
|
}
|