152 lines
4.8 KiB
Rust
Raw Normal View History

2023-02-25 14:49:09 -05:00
use std::str::FromStr;
use spatial_coordinate_systems::{Coordinate, LatLon};
2023-02-25 11:14:25 -05:00
use wasm_bindgen::prelude::*;
2023-03-14 23:26:42 -04:00
use xpin::Address;
2023-02-25 11:14:25 -05:00
#[wasm_bindgen]
#[derive(Debug, Copy, Clone)]
pub enum CoordinateType {
DD,
DMS,
DMM,
UTM,
// Xpin,
Plus,
}
impl Into<spatial_coordinate_systems::CoordinateType> for CoordinateType {
fn into(self) -> spatial_coordinate_systems::CoordinateType {
match self {
Self::DD => spatial_coordinate_systems::CoordinateType::DD,
Self::DMS => spatial_coordinate_systems::CoordinateType::DMS,
Self::DMM => spatial_coordinate_systems::CoordinateType::DMM,
Self::UTM => spatial_coordinate_systems::CoordinateType::UTM,
// Self::Xpin => spatial_coordinate_systems::CoordinateType::Xpin,
Self::Plus => spatial_coordinate_systems::CoordinateType::Plus,
}
}
}
impl From<spatial_coordinate_systems::CoordinateType> for CoordinateType {
fn from(value: spatial_coordinate_systems::CoordinateType) -> CoordinateType {
match value {
spatial_coordinate_systems::CoordinateType::DD => Self::DD,
spatial_coordinate_systems::CoordinateType::DMS => Self::DMS,
spatial_coordinate_systems::CoordinateType::DMM => Self::DMM,
spatial_coordinate_systems::CoordinateType::UTM => Self::UTM,
// spatial_coordinate_systems::CoordinateType::Xpin => Self::Xpin ,
spatial_coordinate_systems::CoordinateType::Plus => Self::Plus,
}
}
}
#[wasm_bindgen(getter_with_clone)]
2023-03-14 23:26:42 -04:00
pub struct EncodedAddress {
pub address: String,
/// The coordinates used to encode this address
src_coords: Coordinate,
#[wasm_bindgen(js_name = srcCoordsRepr)]
pub src_coords_repr: String,
#[wasm_bindgen(js_name = srcCoordsType)]
pub src_coords_type: CoordinateType,
#[wasm_bindgen(js_name = latLon)]
pub lat_lon: Box<[f64]>,
#[wasm_bindgen(js_name = decimalDegrees)]
pub decimal_degrees: String,
2023-02-25 11:14:25 -05:00
}
2023-02-25 14:12:18 -05:00
2023-02-25 14:49:09 -05:00
#[wasm_bindgen]
2023-03-14 23:26:42 -04:00
impl EncodedAddress {
/// Get the string representation of the encoded value
#[wasm_bindgen]
// TODO: Do not return option
pub fn get_coords_repr_as(&self, coordinate_type: CoordinateType) -> Option<String> {
self.src_coords
// TODO: Remove the clone here
.clone()
.as_type(&coordinate_type.into())
.ok()
.map(|s| s.to_string())
}
2023-03-19 13:03:19 -04:00
/// Get an encoded address from a latitude/longitude
2023-03-14 23:26:42 -04:00
#[wasm_bindgen]
pub fn from_lat_lon(lat: f64, lon: f64) -> Result<EncodedAddress, String> {
Self::try_from(
xpin::Address::from_lat_lon(lat, lon)
.as_ref()
.map_err(|e| e.to_string())?,
)
.map_err(|()| String::from("Could not convert xpin to address"))
2023-03-14 23:26:42 -04:00
}
/// Get an encoded address from a latitude/longitude
#[wasm_bindgen]
pub fn from_coordinate(i: &str) -> Result<EncodedAddress, String> {
console_error_panic_hook::set_once();
let src_coords = Coordinate::from_str(i)
.map_err(|()| format!("Could not parse str as a coordinate {i:?}"))?;
// TODO: Remove the clone here
let latlon = LatLon::try_from(src_coords.clone())
.map_err(|_| format!("Could not convert coordinate back to latlon"))?;
let mut ret = Self::try_from(
xpin::Address::from_lat_lon(latlon.lat, latlon.lon)
.as_ref()
.map_err(|e| e.to_string())?,
)
.map_err(|()| String::from("Could not convert xpin to address"))?;
ret.src_coords_repr = src_coords.to_string();
ret.src_coords_type = src_coords.get_type().into();
ret.src_coords = src_coords;
Ok(ret)
}
2023-03-14 23:26:42 -04:00
#[wasm_bindgen]
pub fn from_address(addr_str: &str) -> Result<EncodedAddress, String> {
Self::try_from(
xpin::Address::from_str(addr_str)
.as_ref()
.map_err(|e| e.to_string())?,
)
.map_err(|()| String::from("Could not convert xpin to address"))
2023-03-14 23:26:42 -04:00
}
}
2023-03-14 23:26:42 -04:00
impl TryFrom<&'_ Address<'_>> for EncodedAddress {
type Error = ();
2023-03-14 23:26:42 -04:00
fn try_from(addr: &Address) -> Result<Self, Self::Error> {
console_error_panic_hook::set_once();
2023-03-14 23:26:42 -04:00
let (lat, lon) = addr.as_lat_lon();
let src_coords = Coordinate::from_str(&format!("{}, {}", lat, lon))?;
Ok(Self {
2023-03-14 23:26:42 -04:00
address: addr.to_string(),
// TODO: Do not use formatting here
lat_lon: Box::new([lat, lon]),
src_coords_repr: src_coords.to_string(),
src_coords_type: src_coords.get_type().into(),
src_coords,
decimal_degrees: format!("{}, {}", lat, lon),
})
2023-03-14 23:26:42 -04:00
}
2023-02-25 14:49:09 -05:00
}
// #[cfg(test)]
// mod tests {
// use super::*;
// #[test]
// fn test_general() {
// super::from_address("6532 BROADCAST TINY apple")
// }
// }