use std::str::FromStr; use spatial_coordinate_systems::{Coordinate, LatLon}; use wasm_bindgen::prelude::*; use xpin::Address; #[wasm_bindgen] #[derive(Debug, Copy, Clone)] pub enum CoordinateType { DD, DMS, DMM, UTM, // Xpin, Plus, } impl From for spatial_coordinate_systems::CoordinateType { fn from(val: CoordinateType) -> Self { match val { 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 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)] 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, } #[wasm_bindgen] 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 { self.src_coords // TODO: Remove the clone here .clone() .as_type(&coordinate_type.into()) .ok() .map(|s| s.to_string()) } /// Get an encoded address from a latitude/longitude #[wasm_bindgen] pub fn from_lat_lon(lat: f64, lon: f64) -> Result { 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")) } /// Get an encoded address from a latitude/longitude #[wasm_bindgen] pub fn from_coordinate(i: &str) -> Result { 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::from(&src_coords); let mut ret = Self::try_from( xpin::Address::from_lat_lon(latlon.get_lat(), latlon.get_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) } #[wasm_bindgen] pub fn from_address(addr_str: &str) -> Result { 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")) } } impl TryFrom<&'_ Address<'_>> for EncodedAddress { type Error = (); fn try_from(addr: &Address) -> Result { console_error_panic_hook::set_once(); let (lat, lon) = addr.as_lat_lon(); let src_coords = Coordinate::from_str(&format!("{}, {}", lat, lon))?; Ok(Self { 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), }) } } // #[cfg(test)] // mod tests { // use super::*; // #[test] // fn test_general() { // super::from_address("6532 BROADCAST TINY apple") // } // }