ogcapi_types/common/
extent.rs1use chrono::{DateTime, SecondsFormat, Utc};
2use serde::{Deserialize, Serialize, ser::SerializeSeq, ser::Serializer};
3use serde_with::DisplayFromStr;
4
5use crate::common::{Bbox, Crs};
6
7#[serde_with::skip_serializing_none]
8#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
9pub struct Extent {
10 pub spatial: Option<SpatialExtent>,
11 pub temporal: Option<TemporalExtent>,
12}
13
14impl Default for Extent {
15 fn default() -> Self {
16 Self {
17 spatial: Some(SpatialExtent::default()),
18 temporal: Some(TemporalExtent::default()),
19 }
20 }
21}
22
23#[serde_with::serde_as]
24#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
25pub struct SpatialExtent {
26 #[serde(skip_serializing_if = "Vec::is_empty")]
27 pub bbox: Vec<Bbox>,
28 #[serde(default)]
29 #[serde_as(as = "DisplayFromStr")]
30 pub crs: Crs,
31}
32
33impl Default for SpatialExtent {
34 fn default() -> Self {
35 Self {
36 bbox: vec![Bbox::Bbox2D([-180.0, -90.0, 180.0, 90.0])],
37 crs: Default::default(),
38 }
39 }
40}
41
42#[serde_with::serde_as]
43#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
44pub struct TemporalExtent {
45 #[serde(skip_serializing_if = "Vec::is_empty")]
46 #[serde(serialize_with = "serialize_interval")]
47 pub interval: Vec<Vec<Option<DateTime<Utc>>>>,
48 #[serde(default = "default_trs")]
49 pub trs: String,
50}
51
52impl Default for TemporalExtent {
53 fn default() -> Self {
54 Self {
55 interval: vec![vec![None, None]],
56 trs: default_trs(),
57 }
58 }
59}
60
61fn serialize_interval<S>(
62 interval: &Vec<Vec<Option<DateTime<Utc>>>>,
63 serializer: S,
64) -> Result<S::Ok, S::Error>
65where
66 S: Serializer,
67{
68 let mut outer_seq = serializer.serialize_seq(Some(interval.len()))?;
69 for inner_vec in interval {
70 let serialized_inner_vec: Vec<_> = inner_vec
71 .iter()
72 .map(|item| {
73 item.as_ref()
74 .map(|dt| dt.to_rfc3339_opts(SecondsFormat::Secs, true))
75 })
76 .collect();
77
78 outer_seq.serialize_element(&serialized_inner_vec)?;
79 }
80 outer_seq.end()
81}
82
83fn default_trs() -> String {
84 "http://www.opengis.net/def/uom/ISO-8601/0/Gregorian".to_string()
85}