osmpbfreader/
objects.rs

1// Copyright (c) 2014-2015 Guillaume Pinot <texitoi(a)texitoi.eu>
2//
3// This work is free. You can redistribute it and/or modify it under
4// the terms of the Do What The Fuck You Want To Public License,
5// Version 2, as published by Sam Hocevar. See the COPYING file for
6// more details.
7
8//! This module proposes objects to modelize OpenStreetMap objects.
9//!
10//! There are 3 types of objects: nodes, ways and relations.
11
12#[cfg(feature = "serde")]
13use serde::{Deserialize, Serialize};
14use smartstring::alias::String;
15use std::iter::FromIterator;
16use std::ops::{Deref, DerefMut};
17
18/// Tags represents the features of the objects.  See the
19/// [OpenStreetMap wiki page about
20/// tags](http://wiki.openstreetmap.org/wiki/Tags) for more
21/// information.
22#[derive(Debug, Default, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
23#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
24pub struct Tags(::flat_map::FlatMap<String, String>);
25
26impl Tags {
27    /// Creates a new, empty `Tags` object.
28    pub fn new() -> Tags {
29        Tags(::flat_map::FlatMap::new())
30    }
31
32    /// Returns if it contains a tag with the given `key` and `value`.
33    pub fn contains(&self, key: &str, value: &str) -> bool {
34        self.0.get(key).is_some_and(|v| v.as_str() == value)
35    }
36
37    /// Consume tags into inner FlatMap representation
38    pub fn into_inner(self) -> ::flat_map::FlatMap<String, String> {
39        self.0
40    }
41}
42
43impl Deref for Tags {
44    type Target = ::flat_map::FlatMap<String, String>;
45
46    fn deref(&self) -> &Self::Target {
47        &self.0
48    }
49}
50
51impl DerefMut for Tags {
52    fn deref_mut(&mut self) -> &mut Self::Target {
53        &mut self.0
54    }
55}
56
57impl FromIterator<(String, String)> for Tags {
58    fn from_iter<T: IntoIterator<Item = (String, String)>>(iter: T) -> Self {
59        Tags(iter.into_iter().collect())
60    }
61}
62
63/// A node identifier
64#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Hash, Copy)]
65#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
66pub struct NodeId(pub i64);
67
68/// A way identifier
69#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Hash, Copy)]
70#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
71pub struct WayId(pub i64);
72
73/// A relation identifier
74#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Hash, Copy)]
75#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
76pub struct RelationId(pub i64);
77
78/// An OpenStreetMap object identifier
79#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Hash, Copy)]
80#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
81pub enum OsmId {
82    /// The identifier of a node
83    Node(NodeId),
84    /// The identifier of a way
85    Way(WayId),
86    /// The identifier of a relation
87    Relation(RelationId),
88}
89
90impl OsmId {
91    /// Returns `true` if the id is a node id.
92    pub fn is_node(&self) -> bool {
93        self.node().is_some()
94    }
95    /// Returns `true` if the id is a way id.
96    pub fn is_way(&self) -> bool {
97        self.way().is_some()
98    }
99    /// Returns `true` if the id is a relation id.
100    pub fn is_relation(&self) -> bool {
101        self.relation().is_some()
102    }
103    /// Returns the `NodeId` if it is a node, otherwise returns `None`.
104    pub fn node(&self) -> Option<NodeId> {
105        match *self {
106            OsmId::Node(id) => Some(id),
107            _ => None,
108        }
109    }
110    /// Returns the `WayId` if it is a way, otherwise returns `None`.
111    pub fn way(&self) -> Option<WayId> {
112        match *self {
113            OsmId::Way(id) => Some(id),
114            _ => None,
115        }
116    }
117    /// Returns the `RelationId` if it is a relation, otherwise returns `None`.
118    pub fn relation(&self) -> Option<RelationId> {
119        match *self {
120            OsmId::Relation(id) => Some(id),
121            _ => None,
122        }
123    }
124    /// Returns the inner id.
125    pub fn inner_id(&self) -> i64 {
126        match *self {
127            OsmId::Node(n) => n.0,
128            OsmId::Way(n) => n.0,
129            OsmId::Relation(n) => n.0,
130        }
131    }
132}
133
134/// An OpenStreetMap object.
135#[derive(Debug, PartialEq, PartialOrd, Clone)]
136#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
137pub enum OsmObj {
138    /// A node
139    Node(Node),
140    /// A way
141    Way(Way),
142    /// A relation
143    Relation(Relation),
144}
145
146impl OsmObj {
147    /// Returns the tags of the object.
148    pub fn tags(&self) -> &Tags {
149        match *self {
150            OsmObj::Node(ref node) => &node.tags,
151            OsmObj::Way(ref way) => &way.tags,
152            OsmObj::Relation(ref rel) => &rel.tags,
153        }
154    }
155    /// Returns the id of the object.
156    pub fn id(&self) -> OsmId {
157        match *self {
158            OsmObj::Node(ref node) => OsmId::Node(node.id),
159            OsmObj::Way(ref way) => OsmId::Way(way.id),
160            OsmObj::Relation(ref rel) => OsmId::Relation(rel.id),
161        }
162    }
163    /// Returns `true` if the object is a node.
164    pub fn is_node(&self) -> bool {
165        self.node().is_some()
166    }
167    /// Returns `true` if the object is a way.
168    pub fn is_way(&self) -> bool {
169        self.way().is_some()
170    }
171    /// Returns `true` if the object is a relation.
172    pub fn is_relation(&self) -> bool {
173        self.relation().is_some()
174    }
175    /// Returns a reference to the `Node` if `self` is a node, otherwise returns `None`.
176    pub fn node(&self) -> Option<&Node> {
177        match *self {
178            OsmObj::Node(ref n) => Some(n),
179            _ => None,
180        }
181    }
182    /// Returns a reference to the `Way` if `self` is a way, otherwise returns `None`.
183    pub fn way(&self) -> Option<&Way> {
184        match *self {
185            OsmObj::Way(ref w) => Some(w),
186            _ => None,
187        }
188    }
189    /// Returns a reference to the `Relation` if `self` is a relation, otherwise returns `None`.
190    pub fn relation(&self) -> Option<&Relation> {
191        match *self {
192            OsmObj::Relation(ref r) => Some(r),
193            _ => None,
194        }
195    }
196}
197
198/// An OpenStreetMap node.  See the [OpenStreetMap wiki page about
199/// node](http://wiki.openstreetmap.org/wiki/Node) for more
200/// information.
201#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Hash)]
202#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
203pub struct Node {
204    /// The id of the node.
205    pub id: NodeId,
206    /// The tags of the node.
207    pub tags: Tags,
208    /// The latitude in decimicro degrees (10⁻⁷ degrees).
209    pub decimicro_lat: i32,
210    /// The longitude in decimicro degrees (10⁻⁷ degrees).
211    pub decimicro_lon: i32,
212}
213
214impl Node {
215    /// Returns the latitude of the node in degrees.
216    pub fn lat(&self) -> f64 {
217        self.decimicro_lat as f64 * 1e-7
218    }
219    /// Returns the longitude of the node in degrees.
220    pub fn lon(&self) -> f64 {
221        self.decimicro_lon as f64 * 1e-7
222    }
223}
224
225/// An OpenStreetMap way.  See the [OpenStreetMap wiki page about
226/// way](http://wiki.openstreetmap.org/wiki/Way) for more
227/// information.
228#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Hash)]
229#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
230pub struct Way {
231    /// The id of the way.
232    pub id: WayId,
233    /// The tags of the way.
234    pub tags: Tags,
235    /// The ordered list of nodes as id.
236    pub nodes: Vec<NodeId>,
237}
238
239impl Way {
240    /// Returns true if the way is
241    /// [open](http://wiki.openstreetmap.org/wiki/Way#Open_way).
242    pub fn is_open(&self) -> bool {
243        !self.is_closed()
244    }
245    /// Returns true if the way is
246    /// [closed](http://wiki.openstreetmap.org/wiki/Way#Closed_way).
247    pub fn is_closed(&self) -> bool {
248        self.nodes.first() == self.nodes.last()
249    }
250}
251
252/// A reference to an object with a role.  Used in the relation object.
253#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Hash)]
254#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
255pub struct Ref {
256    /// Id of the member.
257    pub member: OsmId,
258    /// Role of the member.
259    pub role: String,
260}
261
262/// An OpenStreetMap relation.  See the [OpenStreetMap wiki page about
263/// relation](http://wiki.openstreetmap.org/wiki/Relation) for more
264/// information.
265#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Hash)]
266#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
267pub struct Relation {
268    /// The id of the relation.
269    pub id: RelationId,
270    /// The tags of the relation.
271    pub tags: Tags,
272    /// Members of the relation.
273    pub refs: Vec<Ref>,
274}
275
276impl ::std::convert::From<NodeId> for OsmId {
277    fn from(n: NodeId) -> Self {
278        OsmId::Node(n)
279    }
280}
281
282impl ::std::convert::From<WayId> for OsmId {
283    fn from(w: WayId) -> Self {
284        OsmId::Way(w)
285    }
286}
287
288impl ::std::convert::From<RelationId> for OsmId {
289    fn from(r: RelationId) -> Self {
290        OsmId::Relation(r)
291    }
292}
293
294impl ::std::convert::From<Node> for OsmObj {
295    fn from(n: Node) -> Self {
296        OsmObj::Node(n)
297    }
298}
299
300impl ::std::convert::From<Way> for OsmObj {
301    fn from(w: Way) -> Self {
302        OsmObj::Way(w)
303    }
304}
305
306impl ::std::convert::From<Relation> for OsmObj {
307    fn from(r: Relation) -> Self {
308        OsmObj::Relation(r)
309    }
310}