109 lines
2.4 KiB
Rust
109 lines
2.4 KiB
Rust
use serde::{Serialize, Deserialize};
|
|
use std::fmt;
|
|
|
|
macro_rules! tagtype {
|
|
($name:ident: $tag:literal) => {
|
|
#[derive(Clone, Copy, Default, Debug)]
|
|
pub struct $name;
|
|
|
|
impl Serialize for $name {
|
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
|
where
|
|
S: serde::Serializer,
|
|
{
|
|
serializer.serialize_str($tag)
|
|
}
|
|
}
|
|
|
|
impl<'de> Deserialize<'de> for $name {
|
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
|
where
|
|
D: serde::Deserializer<'de>,
|
|
{
|
|
struct Visitor;
|
|
impl serde::de::Visitor<'_> for Visitor {
|
|
type Value = $name;
|
|
|
|
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
|
write!(formatter, "tag type {:?}", $tag)
|
|
}
|
|
|
|
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
|
|
where
|
|
E: serde::de::Error,
|
|
{
|
|
if v != $tag {
|
|
return Err(E::invalid_value(serde::de::Unexpected::Str(v), &$tag));
|
|
}
|
|
Ok($name)
|
|
}
|
|
|
|
}
|
|
deserializer.deserialize_str(Visitor)
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
tagtype!(TagFeatureCollection: "FeatureCollection");
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
|
pub struct FeatureCollection {
|
|
pub r#type: TagFeatureCollection,
|
|
pub features: Vec<Feature>,
|
|
}
|
|
|
|
tagtype!(TagFeature: "Feature");
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
|
pub struct Feature {
|
|
pub r#type: TagFeature,
|
|
pub id: String,
|
|
pub properties: FeatureProperties,
|
|
pub geometry: Geometry,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
|
pub struct FeatureProperties {
|
|
pub name: String,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
|
#[serde(tag = "type")]
|
|
pub enum Geometry {
|
|
Polygon {
|
|
coordinates: PolygonData,
|
|
},
|
|
MultiPolygon {
|
|
coordinates: Vec<PolygonData>,
|
|
},
|
|
}
|
|
|
|
// first list of points is outer "hull" (should be clockwise), remaining list of points are holes (counterclockwise)
|
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
|
pub struct PolygonData(pub Vec<Vec<Position>>);
|
|
|
|
#[derive(Clone, Copy, Debug)]
|
|
pub struct Position {
|
|
pub longitude: f32,
|
|
pub latitude: f32,
|
|
}
|
|
|
|
impl Serialize for Position {
|
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
|
where
|
|
S: serde::Serializer,
|
|
{
|
|
(self.longitude, self.latitude).serialize(serializer)
|
|
}
|
|
}
|
|
|
|
impl<'de> Deserialize<'de> for Position {
|
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
|
where
|
|
D: serde::Deserializer<'de>,
|
|
{
|
|
<(f32, f32)>::deserialize(deserializer).map(|(longitude, latitude)| Position { longitude, latitude })
|
|
}
|
|
}
|