1use std::collections::HashMap;
2use serde::{Deserialize, Deserializer, Serialize, de::Visitor};
3
4#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
8#[serde(rename_all="lowercase", tag="type")]
9pub enum Element {
10 Node(Node),
11 Way(Way),
12 Relation(Relation),
13}
14
15#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
17#[serde(rename_all = "lowercase", tag = "type", content = "ref")]
18pub enum ElementId {
19 Node(i64),
20 Way(i64),
21 Relation(i64),
22}
23
24impl Element {
25 pub fn id(&self) -> ElementId {
27 match self {
28 Self::Node(n) => ElementId::Node(n.id),
29 Self::Way(w) => ElementId::Way(w.id),
30 Self::Relation(r) => ElementId::Relation(r.id),
31 }
32 }
33
34 pub fn tag(&self, name: &str) -> Option<&str> {
36 let tags = match self {
37 Self::Node(n) => &n.tags,
38 Self::Way(w) => &w.tags,
39 Self::Relation(r) => &r.tags,
40 };
41 tags.get(name).map(|s| s.as_str())
42 }
43
44 pub fn tags(&self) -> impl ExactSizeIterator<Item=(&str, &str)> {
46 let tags = match self {
47 Self::Node(n) => &n.tags,
48 Self::Way(w) => &w.tags,
49 Self::Relation(r) => &r.tags,
50 };
51 tags.iter().map(|(k,v)| (k.as_str(), v.as_str()))
52 }
53}
54
55#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
59pub struct Node {
60 pub id: i64,
61 pub lat: f64,
62 pub lon: f64,
63 pub tags: HashMap<String, String>,
64}
65
66#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
70pub struct Way {
71 pub id: i64,
72 pub tags: HashMap<String, String>,
73 pub nodes: Vec<i64>,
74}
75
76#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
80pub struct Relation {
81 pub id: i64,
82 pub tags: HashMap<String, String>,
83 pub members: Vec<RelationMember>,
84}
85
86#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
88pub struct RelationMember {
89 #[serde(flatten)]
90 pub id: ElementId,
91 #[serde(deserialize_with = "skip_empty")]
92 pub role: Option<String>,
93}
94
95fn skip_empty<'de, D>(deserializer: D) -> Result<Option<String>, D::Error> where D: Deserializer<'de> {
96 deserializer.deserialize_string(OptionalStringVisitor)
97}
98
99struct OptionalStringVisitor;
100impl<'de> Visitor<'de> for OptionalStringVisitor {
101 type Value = Option<String>;
102
103 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
104 write!(formatter, "a string")
105 }
106
107 fn visit_string<E>(self, v: String) -> Result<Self::Value, E> where E: serde::de::Error {
108 if v.is_empty() {
109 Ok(None)
110 } else {
111 Ok(Some(v))
112 }
113 }
114}
115
116#[cfg(test)]
117mod test {
118 use super::*;
119
120 #[test]
121 fn id() {
122 let a = ElementId::Node(123);
123 let str = serde_json::to_string(&a).unwrap();
124 assert_eq!(&str, r#"{"type":"node","ref":123}"#);
125 let b: ElementId = serde_json::from_str(&str).unwrap();
126 assert_eq!(a, b);
127 }
128}