osm_api/
elements.rs

1use log::debug;
2use std::str::FromStr;
3
4use chrono::{DateTime, Utc};
5use serde::{Deserialize, Deserializer, Serialize};
6use serde_json::Value;
7
8/// Node is a point in space.
9#[derive(Debug, Clone, Serialize, Deserialize)]
10pub struct Node {
11    #[serde(rename = "@id")]
12    pub id: i64,
13    #[serde(rename = "@lat")]
14    pub lat: f64,
15    #[serde(rename = "@lon")]
16    pub lon: f64,
17    #[serde(rename = "tag", default)]
18    pub tags: Vec<Tag>,
19    #[serde(flatten)]
20    pub attributes: Attributes,
21}
22
23#[derive(Debug, Clone, Serialize, Deserialize)]
24pub struct NodeRef {
25    #[serde(rename = "@ref")]
26    pub reference: i64,
27}
28
29#[derive(Debug, Clone, Serialize, Deserialize)]
30pub struct Way {
31    #[serde(rename = "@id")]
32    pub id: i64,
33    #[serde(rename = "nd", default)]
34    pub nodes: Vec<NodeRef>,
35    #[serde(rename = "tag", default)]
36    pub tags: Vec<Tag>,
37    #[serde(flatten)]
38    pub attributes: Attributes,
39}
40
41#[derive(Debug, Clone, Serialize, Deserialize)]
42pub struct ElementRef {
43    #[serde(rename = "@type")]
44    element_type: ElementType,
45    #[serde(rename = "@ref")]
46    reference: i64,
47    #[serde(rename = "@role")]
48    role: String,
49}
50#[derive(Debug, Clone, Serialize, Deserialize)]
51#[serde(rename_all = "snake_case")]
52pub enum ElementType {
53    Node,
54    Way,
55    Relation,
56}
57#[derive(Debug, Clone, Serialize, Deserialize)]
58pub struct Relation {
59    #[serde(rename = "member", default)]
60    pub members: Vec<ElementRef>,
61    #[serde(rename = "tag", default)]
62    pub tags: Vec<Tag>,
63    #[serde(flatten)]
64    pub attributes: Attributes,
65}
66
67#[derive(Debug, Clone, Serialize, Deserialize)]
68pub struct Tag {
69    #[serde(rename = "@k")]
70    pub key: String,
71    #[serde(rename = "@v")]
72    pub value: String,
73}
74
75#[derive(Debug, Clone, Serialize, Deserialize)]
76pub struct Attributes {
77    #[serde(rename = "@user")]
78    pub user: String,
79    #[serde(rename = "@uid", deserialize_with = "de_from_str")]
80    pub uid: i64,
81    #[serde(rename = "@timestamp")]
82    pub timestamp: TimeStamp,
83    #[serde(rename = "@visible", deserialize_with = "de_from_str")]
84    pub visible: bool,
85    #[serde(rename = "@version", deserialize_with = "de_from_str")]
86    pub version: u8,
87    #[serde(rename = "@changeset", deserialize_with = "de_from_str")]
88    pub changeset: i64,
89}
90
91#[derive(Debug, Clone, Serialize, Deserialize)]
92#[serde(rename = "osm")]
93pub struct OSM {
94    #[serde(alias = "@version", default)]
95    pub version: String,
96    #[serde(alias = "@generator")]
97    pub generator: String,
98    #[serde(rename = "@timestamp")]
99    pub time_stamp_osm_base: Option<TimeStamp>,
100    #[serde(alias = "@copyright")]
101    pub copyright: String,
102    #[serde(alias = "@license")]
103    pub license: String,
104    #[serde(alias = "@attribution")]
105    pub attribution: String,
106    #[serde(rename = "@error")]
107    pub error: Option<String>,
108    #[serde(rename = "node", default)]
109    pub node: Vec<Node>,
110    #[serde(rename = "way", default)]
111    pub way: Vec<Way>,
112    #[serde(rename = "relation", default)]
113    pub relation: Vec<Relation>,
114    pub api: Option<Api>,
115}
116
117type TimeStamp = DateTime<Utc>;
118
119#[derive(Debug, Clone, Serialize, Deserialize, Default)]
120pub struct Api {
121    #[serde(alias = "versions", deserialize_with = "de_inner_version")]
122    pub version: ApiVersion,
123    #[serde(alias = "area", deserialize_with = "de_inner_maximum", default)]
124    #[serde(skip_serializing_if = "Option::is_none")]
125    pub max_areas: Option<f64>,
126    #[serde(alias = "note_area", deserialize_with = "de_inner_maximum", default)]
127    #[serde(skip_serializing_if = "Option::is_none")]
128    pub max_note_areas: Option<i64>,
129    #[serde(alias = "tracepoints", deserialize_with = "de_inner_per_page", default)]
130    #[serde(skip_serializing_if = "Option::is_none")]
131    pub trackpoints_per_page: Option<i64>,
132    #[serde(alias = "waynodes", deserialize_with = "de_inner_maximum", default)]
133    #[serde(skip_serializing_if = "Option::is_none")]
134    pub max_way_nodes: Option<i64>,
135    #[serde(
136        alias = "relationmembers",
137        deserialize_with = "de_inner_maximum",
138        default
139    )]
140    #[serde(skip_serializing_if = "Option::is_none")]
141    pub max_relation_members: Option<i64>,
142    #[serde(alias = "changesets", default)]
143    #[serde(skip_serializing_if = "Option::is_none")]
144    pub changesets: Option<QueryLimit>,
145    #[serde(alias = "notes", default)]
146    #[serde(skip_serializing_if = "Option::is_none")]
147    pub notes: Option<QueryLimit>,
148    #[serde(alias = "timeout", deserialize_with = "de_inner_seconds", default)]
149    #[serde(skip_serializing_if = "Option::is_none")]
150    pub timeout: Option<i64>,
151    #[serde(alias = "status")]
152    #[serde(skip_serializing_if = "Option::is_none")]
153    pub status: Option<ApiStatus>,
154}
155
156#[derive(Debug, Clone, Serialize, Deserialize)]
157pub struct VersionRange {
158    #[serde(alias = "@minimum")]
159    pub min: String,
160    #[serde(alias = "@maximum")]
161    pub max: String,
162}
163
164#[derive(Debug, Clone, Serialize, Deserialize)]
165#[serde(rename_all = "snake_case")]
166pub enum Status {
167    Online,
168    #[serde(alias = "readonly")]
169    ReadOnly,
170    Offline,
171}
172
173#[derive(Debug, Clone, Serialize, Deserialize)]
174pub struct ApiStatus {
175    #[serde(alias = "@database")]
176    pub database: Status,
177    #[serde(alias = "@api")]
178    pub api: Status,
179    #[serde(alias = "@gpx")]
180    pub gpx: Status,
181}
182
183#[derive(Debug, Clone, Serialize, Deserialize)]
184pub struct QueryLimit {
185    #[serde(alias = "@default_query_limit", alias = "default_query_limit")]
186    pub default: i64,
187    #[serde(alias = "@maximum_query_limit", alias = "maximum_query_limit")]
188    pub max: i64,
189    #[serde(alias = "@maximum_elements", alias = "maximum_elements")]
190    pub max_elements: Option<i64>,
191}
192
193#[derive(Debug, Clone, Serialize, Deserialize, Default)]
194pub enum ApiVersion {
195    Versions(Vec<String>),
196    VersionRange(String, String),
197    #[default]
198    None,
199}
200
201fn de_inner_version<'de, D>(deserializer: D) -> Result<ApiVersion, D::Error>
202where
203    D: Deserializer<'de>,
204{
205    let value = Value::deserialize(deserializer)?;
206    debug!("value: {:?}", value);
207    match value {
208        Value::Array(versions) => Ok(ApiVersion::Versions(
209            versions
210                .iter()
211                .map(|v| v.as_str().expect("Not a valid string").to_string())
212                .collect(),
213        )),
214        Value::Object(obj) => {
215            if let Some(version) = obj.get("$text") {
216                return Ok(ApiVersion::Versions(vec![version.to_string()]));
217            }
218            let max = obj
219                .get("@maximum")
220                .or_else(|| obj.get("maximum"))
221                .expect("Missing maximum")
222                .as_str()
223                .expect("Not a valid string")
224                .to_string();
225            let min = obj
226                .get("@minimum")
227                .or_else(|| obj.get("minimum"))
228                .expect("Missing minimum")
229                .as_str()
230                .expect("Not a valid string")
231                .to_string();
232            Ok(ApiVersion::VersionRange(max, min))
233        }
234        _ => Err(serde::de::Error::custom("Invalid version")),
235    }
236}
237
238fn de_inner_maximum<'de, D, T>(deserializer: D) -> Result<Option<T>, D::Error>
239where
240    D: Deserializer<'de>,
241    T: Deserialize<'de>,
242{
243    #[derive(Deserialize)]
244    struct Helper<T> {
245        #[serde(alias = "@maximum")]
246        maximum: Option<T>,
247    }
248    Ok(Helper::<T>::deserialize(deserializer)?.maximum)
249}
250
251fn de_inner_seconds<'de, D, T>(deserializer: D) -> Result<Option<T>, D::Error>
252where
253    D: Deserializer<'de>,
254    T: Deserialize<'de>,
255{
256    #[derive(Deserialize)]
257    struct Helper<T> {
258        #[serde(alias = "@seconds")]
259        seconds: Option<T>,
260    }
261    Ok(Helper::<T>::deserialize(deserializer)?.seconds)
262}
263
264fn de_inner_per_page<'de, D, T>(deserializer: D) -> Result<Option<T>, D::Error>
265where
266    D: Deserializer<'de>,
267    T: Deserialize<'de>,
268{
269    #[derive(Deserialize)]
270    struct Helper<T> {
271        #[serde(alias = "@per_page")]
272        per_page: Option<T>,
273    }
274    Ok(Helper::<T>::deserialize(deserializer)?.per_page)
275}
276
277fn de_from_str<'de, D, T>(deserializer: D) -> Result<T, D::Error>
278where
279    D: Deserializer<'de>,
280    T: FromStr,
281    T::Err: std::fmt::Display,
282{
283    let s = String::deserialize(deserializer)?;
284    T::from_str(&s).map_err(serde::de::Error::custom)
285}