1use log::debug;
2use std::str::FromStr;
3
4use chrono::{DateTime, Utc};
5use serde::{Deserialize, Deserializer, Serialize};
6use serde_json::Value;
7
8#[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}