152 lines
4.5 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,
}
2023-03-24 16:20:56 -04:00
impl From<CoordinateType> for spatial_coordinate_systems::CoordinateType {
fn from(val: CoordinateType) -> Self {
match val {
2023-03-24 18:16:28 -04:00
CoordinateType::DD => Self::DD,
CoordinateType::DMS => Self::DMS,
CoordinateType::DMM => Self::DMM,
CoordinateType::UTM => Self::UTM,
// CoordinateType::Xpin => Self::Xpin,
CoordinateType::Plus => Self::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,
2023-03-25 00:41:27 -04:00
// 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())?,
)
2023-03-25 00:41:27 -04:00
.map_err(|e| e.to_string())
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)
2023-03-25 00:41:27 -04:00
.map_err(|e| format!("Could not parse str {i:?} as a coordinate {e:?}"))?;
// TODO: Remove the clone here
2023-03-25 00:19:42 -04:00
let latlon = LatLon::from(&src_coords);
let mut ret = Self::try_from(
2023-03-25 00:19:42 -04:00
xpin::Address::from_lat_lon(latlon.get_lat(), latlon.get_lon())
.as_ref()
.map_err(|e| e.to_string())?,
)
2023-03-25 00:41:27 -04:00
.map_err(|e| e.to_string())?;
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())?,
)
2023-03-25 00:41:27 -04:00
.map_err(|e| e.to_string())
2023-03-14 23:26:42 -04:00
}
}
2023-03-14 23:26:42 -04:00
impl TryFrom<&'_ Address<'_>> for EncodedAddress {
2023-03-25 00:41:27 -04:00
type Error = String;
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();
2023-03-25 00:41:27 -04:00
// TODO: Do not allocate a string here
let src_coords =
Coordinate::from_str(&format!("{}, {}", lat, lon)).map_err(|e| e.to_string())?;
Ok(Self {
2023-03-14 23:26:42 -04:00
address: addr.to_string(),
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")
// }
// }