osm_xml/
lib.rs

1#![deny(missing_copy_implementations, trivial_numeric_casts, trivial_casts, unused_extern_crates,
2       unused_import_braces, unused_qualifications)]
3
4extern crate fnv;
5extern crate xml;
6
7use std::io::prelude::*;
8use std::str::FromStr;
9
10use xml::reader::{EventReader, XmlEvent};
11use xml::attribute::OwnedAttribute;
12
13pub mod error;
14use error::{Error, ErrorReason};
15use fnv::FnvHashMap;
16
17mod elements;
18pub use elements::{Bounds, Coordinate, Id, Member, Node, Reference, Relation, Role, Tag,
19                   UnresolvedReference, Way};
20mod polygon;
21
22#[derive(Debug)]
23pub struct OSM {
24    pub bounds: Option<Bounds>,
25    pub nodes: FnvHashMap<Id, Node>,
26    pub ways: FnvHashMap<Id, Way>,
27    pub relations: FnvHashMap<Id, Relation>,
28}
29
30impl OSM {
31    fn empty() -> OSM {
32        OSM {
33            bounds: None,
34            nodes: FnvHashMap::default(),
35            ways: FnvHashMap::default(),
36            relations: FnvHashMap::default(),
37        }
38    }
39
40    pub fn parse<R: Read>(source: R) -> Result<OSM, Error> {
41        let mut osm = OSM::empty();
42
43        let mut parser = EventReader::new(source);
44
45        loop {
46            match parse_element_data(&mut parser) {
47                Err(Error::XmlParseError(err)) => return Err(Error::XmlParseError(err)),
48                Err(Error::BoundsMissing(_)) => osm.bounds = None,
49                Err(Error::MalformedTag(_)) |
50                Err(Error::MalformedNode(_)) |
51                Err(Error::MalformedWay(_)) |
52                Err(Error::MalformedRelation(_)) |
53                Err(Error::UnknownElement) => continue,
54                Ok(data) => match data {
55                    ElementData::EndOfDocument => return Ok(osm),
56                    ElementData::Ignored => continue,
57                    ElementData::Bounds(minlat, minlon, maxlat, maxlon) => {
58                        osm.bounds = Some(Bounds {
59                            minlat: minlat,
60                            minlon: minlon,
61                            maxlat: maxlat,
62                            maxlon: maxlon,
63                        });
64                    }
65                    ElementData::Node(id, lat, lon, tags) => {
66                        osm.nodes.insert(
67                            id,
68                            Node {
69                                id: id,
70                                lat: lat,
71                                lon: lon,
72                                tags: tags,
73                            },
74                        );
75                    }
76                    ElementData::Way(id, node_refs, tags) => {
77                        osm.ways.insert(
78                            id,
79                            Way {
80                                id: id,
81                                nodes: node_refs,
82                                tags: tags,
83                            },
84                        );
85                    }
86                    ElementData::Relation(relation) => {
87                        osm.relations.insert(relation.id, relation);
88                    }
89                },
90            }
91        }
92    }
93
94    pub fn resolve_reference<'a>(&self, reference: &UnresolvedReference) -> Reference {
95        match *reference {
96            UnresolvedReference::Node(id) => self.nodes
97                .get(&id)
98                .map(Reference::Node)
99                .unwrap_or(Reference::Unresolved),
100            UnresolvedReference::Way(id) => self.ways
101                .get(&id)
102                .map(Reference::Way)
103                .unwrap_or(Reference::Unresolved),
104            UnresolvedReference::Relation(id) => self.relations
105                .get(&id)
106                .map(Reference::Relation)
107                .unwrap_or(Reference::Unresolved),
108        }
109    }
110}
111
112enum ElementType {
113    Bounds,
114    Node,
115    Way,
116    Relation,
117    Tag,
118    NodeRef,
119    Member,
120}
121
122enum ElementData {
123    Bounds(Coordinate, Coordinate, Coordinate, Coordinate),
124    Node(Id, Coordinate, Coordinate, Vec<Tag>),
125    Way(Id, Vec<UnresolvedReference>, Vec<Tag>),
126    Relation(Relation),
127    // These two are here so we can terminate and skip uninteresting data without
128    // using error handling.
129    EndOfDocument,
130    Ignored,
131}
132
133
134impl FromStr for ElementType {
135    type Err = Error;
136
137    fn from_str(s: &str) -> Result<ElementType, Error> {
138        match s.to_lowercase().as_ref() {
139            "bounds" => Ok(ElementType::Bounds),
140            "node" => Ok(ElementType::Node),
141            "way" => Ok(ElementType::Way),
142            "relation" => Ok(ElementType::Relation),
143            "tag" => Ok(ElementType::Tag),
144            "nd" => Ok(ElementType::NodeRef),
145            "member" => Ok(ElementType::Member),
146            _ => Err(Error::UnknownElement),
147        }
148    }
149}
150
151fn parse_element_data<R: Read>(parser: &mut EventReader<R>) -> Result<ElementData, Error> {
152    let element = try!(parser.next());
153    match element {
154        XmlEvent::EndDocument => Ok(ElementData::EndOfDocument),
155        XmlEvent::StartElement {
156            name, attributes, ..
157        } => {
158            let element_type = try!(ElementType::from_str(&name.local_name));
159
160            match element_type {
161                ElementType::Bounds => parse_bounds(&attributes),
162                ElementType::Node => parse_node(parser, &attributes),
163                ElementType::Way => parse_way(parser, &attributes),
164                ElementType::Relation => parse_relation(parser, &attributes),
165                _ => Err(Error::UnknownElement),
166            }
167        }
168        _ => Ok(ElementData::Ignored),
169    }
170}
171
172fn parse_relation<R: Read>(
173    parser: &mut EventReader<R>,
174    attrs: &Vec<OwnedAttribute>,
175) -> Result<ElementData, Error> {
176    let id = try!(find_attribute("id", attrs).map_err(Error::MalformedRelation));
177
178    let mut members = Vec::new();
179    let mut tags = Vec::new();
180
181    loop {
182        match try!(parser.next()) {
183            XmlEvent::EndElement { name } => {
184                let element_type = try!(ElementType::from_str(&name.local_name));
185
186                match element_type {
187                    ElementType::Relation => {
188                        return Ok(ElementData::Relation(Relation {
189                            id: id,
190                            members: members,
191                            tags: tags,
192                        }))
193                    }
194                    _ => continue,
195                }
196            }
197            XmlEvent::StartElement {
198                name, attributes, ..
199            } => {
200                let element_type = try!(ElementType::from_str(&name.local_name));
201
202                match element_type {
203                    ElementType::Tag => if let Ok(tag) = parse_tag(&attributes) {
204                        tags.push(tag);
205                    },
206                    ElementType::Member => {
207                        let el_type = try!(
208                            find_attribute_uncasted("type", &attributes)
209                                .map_err(Error::MalformedRelation)
210                        );
211                        let el_ref = try!(
212                            find_attribute("ref", &attributes).map_err(Error::MalformedRelation)
213                        );
214                        let el_role = try!(
215                            find_attribute_uncasted("role", &attributes)
216                                .map_err(Error::MalformedRelation)
217                        );
218
219                        let el = match el_type.to_lowercase().as_ref() {
220                            "node" => Member::Node(UnresolvedReference::Node(el_ref), el_role),
221                            "way" => Member::Way(UnresolvedReference::Way(el_ref), el_role),
222                            "relation" => {
223                                Member::Relation(UnresolvedReference::Relation(el_ref), el_role)
224                            }
225                            _ => return Err(Error::MalformedRelation(ErrorReason::Missing)),
226                        };
227
228                        members.push(el);
229                    }
230                    ElementType::Bounds |
231                    ElementType::Node |
232                    ElementType::Relation |
233                    ElementType::Way |
234                    ElementType::NodeRef => {
235                        return Err(Error::MalformedRelation(ErrorReason::IllegalNesting))
236                    }
237                }
238            }
239            _ => continue,
240        }
241    }
242}
243
244fn parse_way<R: Read>(
245    parser: &mut EventReader<R>,
246    attrs: &Vec<OwnedAttribute>,
247) -> Result<ElementData, Error> {
248    let id = try!(find_attribute("id", attrs).map_err(Error::MalformedWay));
249
250    let mut node_refs = Vec::new();
251    let mut tags = Vec::new();
252
253    loop {
254        match try!(parser.next()) {
255            XmlEvent::EndElement { name } => {
256                let element_type = try!(ElementType::from_str(&name.local_name));
257
258                match element_type {
259                    ElementType::Way => return Ok(ElementData::Way(id, node_refs, tags)),
260                    _ => continue,
261                }
262            }
263            XmlEvent::StartElement {
264                name, attributes, ..
265            } => {
266                let element_type = try!(ElementType::from_str(&name.local_name));
267
268                match element_type {
269                    ElementType::Tag => if let Ok(tag) = parse_tag(&attributes) {
270                        tags.push(tag);
271                    },
272                    ElementType::NodeRef => {
273                        let node_ref =
274                            try!(find_attribute("ref", &attributes).map_err(Error::MalformedWay));
275                        node_refs.push(UnresolvedReference::Node(node_ref));
276                    }
277                    ElementType::Bounds |
278                    ElementType::Node |
279                    ElementType::Relation |
280                    ElementType::Way |
281                    ElementType::Member => {
282                        return Err(Error::MalformedWay(ErrorReason::IllegalNesting))
283                    }
284                }
285            }
286            _ => continue,
287        }
288    }
289}
290
291fn parse_node<R: Read>(
292    parser: &mut EventReader<R>,
293    attrs: &Vec<OwnedAttribute>,
294) -> Result<ElementData, Error> {
295    let id = try!(find_attribute("id", attrs).map_err(Error::MalformedNode));
296    let lat = try!(find_attribute("lat", attrs).map_err(Error::MalformedNode));
297    let lon = try!(find_attribute("lon", attrs).map_err(Error::MalformedNode));
298
299    let mut tags = Vec::new();
300
301    loop {
302        match try!(parser.next()) {
303            XmlEvent::EndElement { name } => {
304                let element_type = try!(ElementType::from_str(&name.local_name));
305
306                match element_type {
307                    ElementType::Node => return Ok(ElementData::Node(id, lat, lon, tags)),
308                    _ => continue,
309                }
310            }
311            XmlEvent::StartElement {
312                name, attributes, ..
313            } => {
314                let element_type = try!(ElementType::from_str(&name.local_name));
315
316                match element_type {
317                    ElementType::Tag => if let Ok(tag) = parse_tag(&attributes) {
318                        tags.push(tag);
319                    },
320                    ElementType::Bounds |
321                    ElementType::Node |
322                    ElementType::Relation |
323                    ElementType::Way |
324                    ElementType::NodeRef |
325                    ElementType::Member => {
326                        return Err(Error::MalformedNode(ErrorReason::IllegalNesting))
327                    }
328                }
329            }
330            _ => continue,
331        }
332    }
333}
334
335fn parse_tag(attributes: &Vec<OwnedAttribute>) -> Result<Tag, Error> {
336    let key = try!(find_attribute_uncasted("k", attributes).map_err(Error::MalformedTag));
337    let val = try!(find_attribute_uncasted("v", attributes).map_err(Error::MalformedTag));
338    Ok(Tag { key: key, val: val })
339}
340
341fn parse_bounds(attrs: &Vec<OwnedAttribute>) -> Result<ElementData, Error> {
342    let minlat = try!(find_attribute("minlat", attrs).map_err(Error::BoundsMissing));
343    let minlon = try!(find_attribute("minlon", attrs).map_err(Error::BoundsMissing));
344    let maxlat = try!(find_attribute("maxlat", attrs).map_err(Error::BoundsMissing));
345    let maxlon = try!(find_attribute("maxlon", attrs).map_err(Error::BoundsMissing));
346
347    Ok(ElementData::Bounds(minlat, minlon, maxlat, maxlon))
348}
349
350fn find_attribute<T>(name: &str, attrs: &Vec<OwnedAttribute>) -> Result<T, ErrorReason>
351where
352    ErrorReason: From<<T as std::str::FromStr>::Err>,
353    T: FromStr,
354{
355    let val_raw = try!(find_attribute_uncasted(name, attrs));
356    let val = try!(val_raw.parse::<T>());
357    Ok(val)
358}
359
360fn find_attribute_uncasted(name: &str, attrs: &Vec<OwnedAttribute>) -> Result<String, ErrorReason> {
361    let attr = attrs.iter().find(|attr| attr.name.local_name == name);
362    match attr {
363        Some(a) => Ok(a.value.clone()),
364        None => Err(ErrorReason::Missing),
365    }
366}