use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use serde_json::Value;
use serde_repr::{Deserialize_repr, Serialize_repr};
use serde_with::DisplayFromStr;
use crate::common::Links;
use super::{BoundingBox2D, Crs, Point2D, TitleDescriptionKeywords};
#[serde_with::serde_as]
#[serde_with::skip_serializing_none]
#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
pub struct TileSets {
pub tilesets: Vec<TileSetItem>,
pub links: Option<Links>,
}
#[serde_with::serde_as]
#[serde_with::skip_serializing_none]
#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
pub struct TileSetItem {
pub title: Option<String>,
pub data_type: DataType,
#[serde_as(as = "DisplayFromStr")]
pub crs: Crs,
#[serde(rename = "tileMatrixSetURI")]
pub tile_matrix_set_uri: Option<String>,
pub links: Links,
}
#[serde_with::serde_as]
#[serde_with::skip_serializing_none]
#[derive(Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct TileSet {
#[serde(flatten)]
pub title_description_keywords: TitleDescriptionKeywords,
pub data_type: DataType,
#[serde(rename = "tileMatrixSetURI")]
pub tile_matrix_set_uri: Option<String>,
pub tile_matrix_set_limits: Option<Vec<TileMatrixLimits>>,
#[serde_as(as = "DisplayFromStr")]
pub crs: Crs,
pub epoch: Option<f64>,
pub links: Links,
pub layers: Option<Vec<GeospatialData>>,
pub bounding_box: Option<BoundingBox2D>,
pub style: Option<Style>,
pub center_point: Option<TilePoint>,
pub license: Option<String>,
pub access_constraints: Option<AccessConstraints>,
pub version: Option<String>,
pub created: Option<DateTime<Utc>>,
pub updated: Option<DateTime<Utc>>,
pub point_of_contact: Option<String>,
pub media_types: Option<Vec<String>>,
}
#[serde_with::serde_as]
#[serde_with::skip_serializing_none]
#[derive(Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct GeospatialData {
#[serde(flatten)]
pub title_description_keywords: TitleDescriptionKeywords,
pub id: String,
pub data_type: DataType,
pub geometry_dimension: Option<GeometryDimension>,
pub feature_type: Option<String>,
pub point_of_contact: Option<String>,
pub publisher: Option<String>,
pub theme: Option<String>,
#[serde_as(as = "Option<DisplayFromStr>")]
pub crs: Option<Crs>,
pub epoch: Option<f64>,
pub min_scale_denominator: Option<f64>,
pub max_scale_denominator: Option<f64>,
pub min_cell_size: Option<f64>,
pub max_cell_size: Option<f64>,
pub max_tile_matrix: Option<String>,
pub min_tile_matrix: Option<String>,
pub bounding_box: Option<BoundingBox2D>,
pub created: Option<DateTime<Utc>>,
pub updated: Option<DateTime<Utc>>,
pub style: Option<Style>,
pub geo_data_classes: Option<Vec<String>>,
pub properties_schema: Option<Value>,
pub links: Option<Links>,
}
#[serde_with::serde_as]
#[serde_with::skip_serializing_none]
#[derive(Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct TilePoint {
pub coordinates: Option<Point2D>,
#[serde_as(as = "Option<DisplayFromStr>")]
pub crs: Option<Crs>,
pub tile_matrix: Option<String>,
pub scale_denominator: Option<f64>,
pub cell_size: Option<f64>,
}
#[serde_with::serde_as]
#[serde_with::skip_serializing_none]
#[derive(Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Style {
#[serde(flatten)]
pub title_description_keywords: TitleDescriptionKeywords,
pub id: String,
pub links: Option<Links>,
}
#[derive(Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct TileMatrixLimits {
pub tile_matrix: String,
pub min_tile_row: u64,
pub max_tile_row: u64,
pub min_tile_col: u64,
pub max_tile_col: u64,
}
#[derive(Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
#[non_exhaustive]
pub enum DataType {
Map,
Vector,
Coverage,
}
#[repr(u8)]
#[derive(Serialize_repr, Deserialize_repr, PartialEq, Eq, Debug)]
pub enum GeometryDimension {
Points = 0,
Curves = 1,
Surfaces = 2,
Solids = 3,
}
#[derive(Serialize, Deserialize, Default)]
#[serde(rename_all = "camelCase")]
pub enum AccessConstraints {
#[default]
Unclassified,
Restricted,
Confidential,
Secret,
TopSecret,
}
#[cfg(test)]
mod test {
use super::GeometryDimension;
#[test]
fn geometry_dimension() {
assert_eq!(
serde_json::from_str::<GeometryDimension>("0").unwrap(),
GeometryDimension::Points
);
assert_eq!(
serde_json::to_value(&GeometryDimension::Points)
.unwrap()
.as_u64(),
Some(0)
);
}
}