use crate::{
AddressError, AddressErrorKind, AddressStatus, CommonAddress, CommonAddresses, Decode,
GeoAddress, GeoAddresses, IntoBin, IntoCsv, Io, SpatialAddress, SpatialAddresses, State,
StreetNamePostType, StreetNamePreDirectional, StreetNamePreModifier, StreetNamePreType,
StreetSeparator, SubaddressType, deserialize_arcgis_data, from_bin, from_csv, to_bin, to_csv,
};
#[derive(Debug, Default, Clone, PartialEq, PartialOrd, serde::Serialize, serde::Deserialize)]
pub struct SpatialAddressRaw {
pub number: i64,
#[serde(deserialize_with = "deserialize_arcgis_data")]
pub number_suffix: Option<String>,
#[serde(deserialize_with = "StreetNamePreDirectional::deserialize_mixed")]
pub directional: Option<StreetNamePreDirectional>,
#[serde(deserialize_with = "StreetNamePreModifier::deserialize_mixed")]
pub pre_modifier: Option<StreetNamePreModifier>,
#[serde(deserialize_with = "StreetNamePreType::deserialize_mixed")]
pub pre_type: Option<StreetNamePreType>,
#[serde(deserialize_with = "StreetSeparator::deserialize_mixed")]
pub separator: Option<StreetSeparator>,
pub street_name: String,
#[serde(deserialize_with = "StreetNamePostType::deserialize_mixed")]
pub street_type: Option<StreetNamePostType>,
#[serde(deserialize_with = "SubaddressType::deserialize_mixed")]
pub subaddress_type: Option<SubaddressType>,
#[serde(deserialize_with = "deserialize_arcgis_data")]
pub subaddress_id: Option<String>,
#[serde(deserialize_with = "csv::invalid_option")]
pub floor: Option<i64>,
#[serde(deserialize_with = "deserialize_arcgis_data")]
pub building: Option<String>,
pub zip: i64,
pub postal_community: String,
#[serde(deserialize_with = "State::deserialize_mixed")]
pub state: State,
pub status: AddressStatus,
pub latitude: f64,
pub longitude: f64,
pub x: f64,
pub y: f64,
}
impl From<SpatialAddressRaw> for CommonAddress {
fn from(value: SpatialAddressRaw) -> Self {
Self {
number: value.number,
number_suffix: value.number_suffix,
directional: value.directional,
pre_modifier: value.pre_modifier,
pre_type: value.pre_type,
separator: value.separator,
street_name: value.street_name,
street_type: value.street_type,
subaddress_type: value.subaddress_type,
subaddress_id: value.subaddress_id,
floor: value.floor,
building: value.building,
zip: value.zip,
postal_community: value.postal_community,
state: value.state,
status: value.status,
}
}
}
impl From<SpatialAddressRaw> for GeoAddress {
fn from(value: SpatialAddressRaw) -> Self {
let address = CommonAddress::from(value.clone());
Self {
address,
longitude: value.longitude,
latitude: value.latitude,
}
}
}
impl From<SpatialAddressRaw> for SpatialAddress {
fn from(value: SpatialAddressRaw) -> Self {
let address = CommonAddress::from(value.clone());
Self {
address,
longitude: value.longitude,
latitude: value.latitude,
x: value.x,
y: value.y,
}
}
}
#[derive(
Debug,
Default,
Clone,
PartialEq,
PartialOrd,
serde::Serialize,
serde::Deserialize,
derive_more::Deref,
derive_more::DerefMut,
)]
pub struct SpatialAddressesRaw(Vec<SpatialAddressRaw>);
impl From<SpatialAddressesRaw> for CommonAddresses {
fn from(value: SpatialAddressesRaw) -> Self {
let raw = value
.iter()
.map(|x| CommonAddress::from(x.clone()))
.collect::<Vec<CommonAddress>>();
Self::new(raw)
}
}
impl From<SpatialAddressesRaw> for GeoAddresses {
fn from(value: SpatialAddressesRaw) -> Self {
let raw = value
.iter()
.map(|x| GeoAddress::from(x.clone()))
.collect::<Vec<GeoAddress>>();
Self::new(raw)
}
}
impl From<SpatialAddressesRaw> for SpatialAddresses {
fn from(value: SpatialAddressesRaw) -> Self {
let raw = value
.iter()
.map(|x| SpatialAddress::from(x.clone()))
.collect::<Vec<SpatialAddress>>();
Self::new(raw)
}
}
impl IntoBin<SpatialAddressesRaw> for SpatialAddressesRaw {
fn load<P: AsRef<std::path::Path>>(path: P) -> Result<Self, AddressError> {
let config = bincode::config::standard();
match from_bin(path) {
Ok(records) => {
let (results, _) = bincode::serde::decode_from_slice::<
Self,
bincode::config::Configuration,
>(&records, config)
.map_err(|source| Decode::new(source, line!(), file!().into()))?;
Ok(results)
}
Err(source) => Err(AddressErrorKind::from(source).into()),
}
}
fn save<P: AsRef<std::path::Path>>(&self, path: P) -> Result<(), AddressError> {
to_bin(self, path)
}
}
impl IntoCsv<SpatialAddressesRaw> for SpatialAddressesRaw {
fn from_csv<P: AsRef<std::path::Path>>(path: P) -> Result<Self, Io> {
let records = from_csv(path)?;
Ok(Self(records))
}
fn to_csv<P: AsRef<std::path::Path>>(&mut self, path: P) -> Result<(), AddressErrorKind> {
to_csv(&mut self.0, path.as_ref().into())
}
}