use crate::{
config::OneOrMany,
model::{map::SpatialIndexType, unit::DistanceUnit},
};
use serde::{Deserialize, Serialize};
use serde_json::Value;
use uom::si::f64::Length;
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct MapModelConfig {
pub tolerance: Option<DistanceTolerance>,
pub spatial_index_type: Option<SpatialIndexType>,
pub matching_type: Option<Vec<String>>,
pub geometry: OneOrMany<MapModelGeometryConfig>,
pub queries_without_destinations: bool,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum MapModelGeometryConfig {
FromVertices,
FromLinestrings {
geometry_input_file: String,
},
}
impl Default for MapModelConfig {
fn default() -> Self {
Self {
tolerance: Default::default(),
matching_type: Default::default(),
spatial_index_type: Default::default(),
geometry: OneOrMany::One(MapModelGeometryConfig::FromVertices),
queries_without_destinations: Default::default(),
}
}
}
impl TryFrom<Option<&Value>> for MapModelConfig {
type Error = String;
fn try_from(value: Option<&Value>) -> Result<Self, Self::Error> {
match value {
None => Ok(MapModelConfig::default()),
Some(json) => {
let map_model_config: MapModelConfig =
serde_json::from_value(json.clone()).map_err(|e| {
let map_model_str = serde_json::to_string_pretty(&json).unwrap_or_default();
format!(
"unable to deserialize map model configuration section due to '{e}'. input data: \n{map_model_str}"
)
})?;
Ok(map_model_config)
}
}
}
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct DistanceTolerance {
pub distance: f64,
pub unit: DistanceUnit,
}
impl DistanceTolerance {
pub fn to_uom(&self) -> Length {
self.unit.to_uom(self.distance)
}
}
impl std::fmt::Display for DistanceTolerance {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{} {}", self.distance, self.unit)
}
}