1extern crate byteorder;
15extern crate chrono;
16extern crate flate2;
17extern crate protobuf;
18extern crate quick_xml;
19extern crate xml as xml_rs;
20#[macro_use]
21extern crate derive_builder;
22extern crate anyhow;
23extern crate bzip2;
24extern crate serde;
25extern crate serde_json;
26extern crate smallvec;
27extern crate smol_str;
28
29use serde::{Deserialize, Serialize};
30use std::collections::HashMap;
31use std::convert::{TryFrom, TryInto};
32use std::fmt;
33use std::fmt::Debug;
34use std::fmt::Display;
35use std::fs::File;
36use std::io::{BufReader, Read, Write};
37use std::iter::{ExactSizeIterator, Iterator};
38use std::path::Path;
39use std::str::FromStr;
40use utils::{epoch_to_iso, iso_to_epoch};
41
42use anyhow::Result;
43
44#[macro_use]
45pub mod utils;
46
47pub mod arcpbf;
48pub mod pbf;
49pub mod stringpbf;
50pub mod xml;
51pub mod osc;
53
54pub mod obj_types;
55
56#[cfg(test)]
57mod tests;
58
59pub mod changesets;
60
61pub type ObjId = i64;
63
64pub const COORD_PRECISION_NANOS: i32 = 100;
67
68pub const COORD_SCALE_FACTOR: f64 = (1_000_000_000 / COORD_PRECISION_NANOS) as f64;
72
73pub mod prelude {
74 pub use crate::OSMObj;
76 pub use crate::OSMObjectType;
77 pub use crate::OSMReader;
78 pub use crate::{Node, Relation, Way};
79}
80
81pub fn lat_lon_inner_to_degrees(inner: i32) -> f64 {
82 inner as f64 / COORD_SCALE_FACTOR
83}
84
85macro_rules! lat_lon_impl {
86 ($lat_or_lon: ident) => {
87 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
100 pub struct $lat_or_lon(i32);
101
102 impl $lat_or_lon {
103 pub fn from_inner(inner: i32) -> Self {
111 Self(inner)
112 }
113
114 pub fn inner(&self) -> i32 {
115 self.0
116 }
117
118 pub fn degrees(&self) -> f64 {
124 lat_lon_inner_to_degrees(self.0)
125 }
126 }
127
128 impl Display for $lat_or_lon {
129 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
130 Display::fmt(&self.degrees(), f)
132 }
133 }
134
135 impl Debug for $lat_or_lon {
136 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
137 Debug::fmt(&self.degrees(), f)
139 }
140 }
141
142 impl FromStr for $lat_or_lon {
155 type Err = ParseLatLonError;
156
157 fn from_str(s: &str) -> Result<Self, Self::Err> {
158 match (f64::from_str(s)? * COORD_SCALE_FACTOR).round() {
159 x if x > (i32::MAX as f64) => Err(ParseLatLonError::TooLarge(x)),
160 x if x < (i32::MIN as f64) => Err(ParseLatLonError::TooSmall(x)),
161 x => Ok(Self(x as i32)),
162 }
163 }
164 }
165
166 impl From<$lat_or_lon> for f64 {
167 fn from(val: $lat_or_lon) -> f64 {
168 val.degrees()
169 }
170 }
171
172 impl TryFrom<f64> for $lat_or_lon {
173 type Error = ParseLatLonError;
174 fn try_from(val: f64) -> Result<$lat_or_lon, Self::Error> {
175 match (val * COORD_SCALE_FACTOR).round() {
176 x if x > (i32::MAX as f64) => Err(ParseLatLonError::TooLarge(x)),
177 x if x < (i32::MIN as f64) => Err(ParseLatLonError::TooSmall(x)),
178 x => Ok(Self(x as i32)),
179 }
180 }
181 }
182
183 impl TryFrom<f32> for $lat_or_lon {
184 type Error = ParseLatLonError;
185 fn try_from(val: f32) -> Result<$lat_or_lon, Self::Error> {
186 $lat_or_lon::try_from(val as f64)
187 }
188 }
189 };
190}
191
192lat_lon_impl!(Lat);
194
195lat_lon_impl!(Lon);
197
198#[derive(Debug)]
200pub enum ParseLatLonError {
201 ParseFloatError(std::num::ParseFloatError),
203
204 TooLarge(f64),
209
210 TooSmall(f64),
215}
216
217impl std::error::Error for ParseLatLonError {
218 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
219 if let Self::ParseFloatError(inner) = self {
220 Some(inner)
221 } else {
222 None
223 }
224 }
225}
226
227impl Display for ParseLatLonError {
228 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
229 match self {
230 Self::ParseFloatError(inner) => Display::fmt(inner, f),
231 Self::TooLarge(float) => write!(f, "{} is too large to represent as a Lat/Lon", float),
232 Self::TooSmall(float) => write!(f, "{} is too small to represent as a Lat/Lon", float),
233 }
234 }
235}
236
237impl From<std::num::ParseFloatError> for ParseLatLonError {
238 fn from(err: std::num::ParseFloatError) -> Self {
239 ParseLatLonError::ParseFloatError(err)
240 }
241}
242
243#[derive(Debug, Clone, Eq, Serialize, Deserialize)]
248pub enum TimestampFormat {
249 ISOString(String),
250 EpochNunber(i64),
251}
252
253impl TimestampFormat {
254 pub fn to_iso_string(&self) -> String {
255 match self {
256 TimestampFormat::ISOString(s) => s.clone(),
257 TimestampFormat::EpochNunber(t) => epoch_to_iso(*t as i32),
258 }
259 }
260
261 pub fn to_epoch_number(&self) -> i64 {
262 match self {
263 TimestampFormat::ISOString(s) => iso_to_epoch(s) as i64,
264 &TimestampFormat::EpochNunber(t) => t,
265 }
266 }
267}
268
269impl<T> From<T> for TimestampFormat
270where
271 T: Into<i64>,
272{
273 fn from(v: T) -> Self {
274 TimestampFormat::EpochNunber(v.into())
275 }
276}
277
278impl std::str::FromStr for TimestampFormat {
279 type Err = String;
280
281 fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
282 let date: i64 = chrono::DateTime::parse_from_rfc3339(s)
283 .map_err(|_| "invalid date")?
284 .timestamp();
285 Ok(TimestampFormat::EpochNunber(date))
286 }
287}
288
289impl fmt::Display for TimestampFormat {
290 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
291 write!(f, "{}", self.to_iso_string())
292 }
293}
294
295impl std::cmp::PartialOrd for TimestampFormat {
296 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
297 match (self, other) {
298 (TimestampFormat::ISOString(a), TimestampFormat::ISOString(b)) => a.partial_cmp(b),
299 (TimestampFormat::EpochNunber(a), TimestampFormat::EpochNunber(b)) => a.partial_cmp(b),
300 (a, b) => a.to_epoch_number().partial_cmp(&b.to_epoch_number()),
301 }
302 }
303}
304impl std::cmp::PartialEq for TimestampFormat {
305 fn eq(&self, other: &Self) -> bool {
306 match (self, other) {
307 (TimestampFormat::ISOString(a), TimestampFormat::ISOString(b)) => a.eq(b),
308 (TimestampFormat::EpochNunber(a), TimestampFormat::EpochNunber(b)) => a.eq(b),
309 (a, b) => a.to_epoch_number().eq(&b.to_epoch_number()),
310 }
311 }
312}
313
314pub trait OSMObjBase: PartialEq + Debug + Clone {
316 fn id(&self) -> ObjId;
317 fn set_id(&mut self, val: impl Into<ObjId>);
318 fn version(&self) -> Option<u32>;
319 fn set_version(&mut self, val: impl Into<Option<u32>>);
320 fn deleted(&self) -> bool;
321 fn set_deleted(&mut self, val: bool);
322 fn changeset_id(&self) -> Option<u32>;
323 fn set_changeset_id(&mut self, val: impl Into<Option<u32>>);
324 fn timestamp(&self) -> &Option<TimestampFormat>;
325 fn set_timestamp(&mut self, val: impl Into<Option<TimestampFormat>>);
326 fn uid(&self) -> Option<u32>;
327 fn set_uid(&mut self, val: impl Into<Option<u32>>);
328 fn user(&self) -> Option<&str>;
329 fn set_user<'a>(&mut self, val: impl Into<Option<&'a str>>);
330
331 fn tags<'a>(&'a self) -> Box<dyn ExactSizeIterator<Item = (&'a str, &'a str)> + 'a>;
332 fn tag(&self, key: impl AsRef<str>) -> Option<&str>;
333 fn has_tag(&self, key: impl AsRef<str>) -> bool {
334 self.tag(key).is_some()
335 }
336 fn num_tags(&self) -> usize {
337 self.tags().count()
338 }
339 fn tags_json_string(&self) -> String {
341 if self.untagged() {
342 return "{}".to_string();
343 }
344 let mut t = serde_json::Map::new();
345 for (k, v) in self.tags() {
346 t.insert(k.to_string(), serde_json::Value::String(v.to_string()));
347 }
348 serde_json::Value::Object(t).to_string()
349 }
350
351 fn tagged(&self) -> bool {
353 !self.untagged()
354 }
355 fn untagged(&self) -> bool {
357 self.num_tags() == 0
358 }
359
360 fn set_tag(&mut self, key: impl AsRef<str>, value: impl Into<String>);
361 fn unset_tag(&mut self, key: impl AsRef<str>);
362
363 fn strip_metadata(&mut self) {
364 self.set_uid(None);
365 self.set_user(None);
366 self.set_changeset_id(None);
367 }
368
369 fn object_type(&self) -> OSMObjectType;
370}
371
372pub trait Node: OSMObjBase {
374 fn lat_lon(&self) -> Option<(Lat, Lon)>;
376
377 fn lat_lon_f64(&self) -> Option<(f64, f64)> {
379 self.lat_lon().map(|(lat, lon)| (lat.into(), lon.into()))
380 }
381 fn has_lat_lon(&self) -> bool {
383 self.lat_lon().is_some()
384 }
385
386 fn unset_lat_lon(&mut self) {
388 self.set_lat_lon_direct(None);
389 }
390
391 fn set_lat_lon_direct(&mut self, loc: Option<(Lat, Lon)>);
393
394 fn set_lat_lon<LL, L1, L2>(&mut self, loc: LL) -> Result<(), ParseLatLonError>
415 where
416 L1: TryInto<Lat>,
417 L2: TryInto<Lon>,
418 LL: Into<Option<(L1, L2)>>,
419 ParseLatLonError: From<<L1 as TryInto<Lat>>::Error>,
420 ParseLatLonError: From<<L2 as TryInto<Lon>>::Error>,
421 {
422 let ll: Option<(L1, L2)> = loc.into();
423 match ll {
424 None => self.set_lat_lon_direct(None),
425 Some((l1, l2)) => {
426 let l1: Lat = l1.try_into()?;
427 let l2: Lon = l2.try_into()?;
428 self.set_lat_lon_direct(Some((l1, l2)));
429 }
430 }
431 Ok(())
432 }
433}
434
435pub trait Way: OSMObjBase {
437 fn nodes(&self) -> &[ObjId];
439
440 fn nids(&self) -> &[ObjId] {
442 self.nodes()
443 }
444 fn num_nodes(&self) -> usize;
446 fn node(&self, idx: usize) -> Option<ObjId>;
448 fn set_nodes(&mut self, nodes: impl IntoIterator<Item = impl Into<ObjId>>);
449
450 fn is_closed(&self) -> bool {
456 match (self.nodes().first(), self.nodes().last()) {
457 (Some(a), Some(b)) => a == b,
458 _ => false,
459 }
460 }
461
462 fn is_area(&self) -> bool {
465 self.is_closed() && self.tag("area") != Some("no")
471 }
472}
473
474pub trait Relation: OSMObjBase {
476 fn members<'a>(
477 &'a self,
478 ) -> Box<dyn ExactSizeIterator<Item = (OSMObjectType, ObjId, &'a str)> + 'a>;
479 fn set_members(
480 &mut self,
481 members: impl IntoIterator<Item = (OSMObjectType, ObjId, impl Into<String>)>,
482 );
483}
484
485#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
487pub enum OSMObjectType {
488 Node,
489 Way,
490 Relation,
491}
492
493impl OSMObjectType {
494 pub fn name_short(&self) -> &str {
495 match self {
496 OSMObjectType::Node => "n",
497 OSMObjectType::Way => "w",
498 OSMObjectType::Relation => "r",
499 }
500 }
501 pub fn name_long(&self) -> &str {
502 match self {
503 OSMObjectType::Node => "node",
504 OSMObjectType::Way => "way",
505 OSMObjectType::Relation => "relation",
506 }
507 }
508}
509
510impl std::fmt::Debug for OSMObjectType {
511 fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
512 write!(f, "{}", self.name_short())
513 }
514}
515
516impl std::fmt::Display for OSMObjectType {
517 fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
518 write!(f, "{}", self.name_long())
519 }
520}
521
522impl TryFrom<char> for OSMObjectType {
523 type Error = String;
524
525 fn try_from(c: char) -> Result<Self, Self::Error> {
526 match c {
527 'n' => Ok(OSMObjectType::Node),
528 'w' => Ok(OSMObjectType::Way),
529 'r' => Ok(OSMObjectType::Relation),
530 _ => Err(format!("Cannot convert {} to OSMObjectType", c)),
531 }
532 }
533}
534
535impl std::str::FromStr for OSMObjectType {
536 type Err = String;
537
538 fn from_str(s: &str) -> Result<Self, Self::Err> {
539 match s {
540 "n" | "node" => Ok(OSMObjectType::Node),
541 "w" | "way" => Ok(OSMObjectType::Way),
542 "r" | "relation" | "rel" => Ok(OSMObjectType::Relation),
543 _ => Err(format!("Cannot convert {} to OSMObjectType", s)),
544 }
545 }
546}
547
548pub trait OSMObj: OSMObjBase {
550 type Node: Node;
552 type Way: Way;
554 type Relation: Relation;
556
557 fn into_node(self) -> Option<Self::Node>;
558 fn into_way(self) -> Option<Self::Way>;
559 fn into_relation(self) -> Option<Self::Relation>;
560
561 fn as_node(&self) -> Option<&Self::Node>;
562 fn as_way(&self) -> Option<&Self::Way>;
563 fn as_relation(&self) -> Option<&Self::Relation>;
564
565 fn as_node_mut(&mut self) -> Option<&mut Self::Node>;
566 fn as_way_mut(&mut self) -> Option<&mut Self::Way>;
567 fn as_relation_mut(&mut self) -> Option<&mut Self::Relation>;
568
569 fn is_node(&self) -> bool {
570 self.object_type() == OSMObjectType::Node
571 }
572 fn is_way(&self) -> bool {
573 self.object_type() == OSMObjectType::Way
574 }
575 fn is_relation(&self) -> bool {
576 self.object_type() == OSMObjectType::Relation
577 }
578}
579
580pub trait OSMReader {
582 type R: Read;
584 type Obj: OSMObj;
586
587 fn new(_: Self::R) -> Self;
589
590 #[allow(unused_variables)]
591 fn set_sorted_assumption(&mut self, sorted_assumption: bool) {}
592 fn get_sorted_assumption(&mut self) -> bool {
593 false
594 }
595
596 fn assume_sorted(&mut self) {
597 self.set_sorted_assumption(true);
598 }
599 fn assume_unsorted(&mut self) {
600 self.set_sorted_assumption(false);
601 }
602
603 fn into_inner(self) -> Self::R;
605
606 fn inner(&self) -> &Self::R;
608
609 fn next(&mut self) -> Option<Self::Obj>;
611
612 fn objects(&mut self) -> OSMObjectIterator<'_, Self>
614 where
615 Self: Sized,
616 {
617 OSMObjectIterator { inner: self }
618 }
619
620 fn nodes(&mut self) -> Box<dyn Iterator<Item = <<Self as OSMReader>::Obj as OSMObj>::Node> + '_>
621 where
622 Self: Sized,
623 {
624 Box::new(self.objects().filter_map(|o| o.into_node()))
625 }
626
627 fn ways(&mut self) -> Box<dyn Iterator<Item = <<Self as OSMReader>::Obj as OSMObj>::Way> + '_>
628 where
629 Self: Sized,
630 {
631 Box::new(self.objects().filter_map(|o| o.into_way()))
632 }
633
634 fn relations(
635 &mut self,
636 ) -> Box<dyn Iterator<Item = <<Self as OSMReader>::Obj as OSMObj>::Relation> + '_>
637 where
638 Self: Sized,
639 {
640 Box::new(self.objects().filter_map(|o| o.into_relation()))
641 }
642
643 }
659
660pub struct OSMObjectIterator<'a, R>
664where
665 R: OSMReader + 'a,
666{
667 inner: &'a mut R,
668}
669
670impl<'a, R> OSMObjectIterator<'a, R>
671where
672 R: OSMReader,
673{
674 pub fn inner(&self) -> &R {
675 self.inner
676 }
677}
678
679impl<'a, R> Iterator for OSMObjectIterator<'a, R>
680where
681 R: OSMReader,
682{
683 type Item = R::Obj;
684
685 fn next(&mut self) -> Option<Self::Item> {
686 self.inner.next()
687 }
688}
689
690#[derive(Debug)]
692pub enum OSMWriteError {
693 FormatDoesntSupportHeaders,
694 AlreadyStarted,
695 AlreadyClosed,
696 OPLWrite(::std::io::Error),
697 XMLWriteXMLError(quick_xml::Error),
698 XMLWriteIOError(::std::io::Error),
699}
700impl std::fmt::Display for OSMWriteError {
701 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
702 write!(f, "{:?}", self)
703 }
704}
705impl std::error::Error for OSMWriteError {}
706
707pub trait OSMWriter<W: Write> {
709 fn new(_: W) -> Self;
711
712 fn close(&mut self) -> Result<(), OSMWriteError>;
719
720 fn is_open(&self) -> bool;
724
725 fn write_obj(&mut self, obj: &impl OSMObj) -> Result<(), OSMWriteError>;
727
728 fn into_inner(self) -> W;
730
731 fn set_header(&mut self, _key_value: (&str, &str)) -> Result<(), OSMWriteError> {
732 todo!("set_header not done yet")
733 }
734
735 fn from_iter<I: Iterator<Item = impl OSMObj>>(writer: W, iter: I) -> Self
738 where
739 Self: Sized,
740 {
741 let mut writer = Self::new(writer);
742
743 for obj in iter {
745 writer.write_obj(&obj).unwrap();
746 }
747 writer.close().unwrap();
748
749 writer
750 }
751}
752
753pub fn version<'a>() -> &'a str {
757 option_env!("CARGO_PKG_VERSION").unwrap_or("unknown-non-cargo-build")
758}
759
760pub fn read_pbf(filename: impl AsRef<Path>) -> Result<pbf::PBFReader<BufReader<File>>> {
762 pbf::PBFReader::from_filename(filename)
763}
764
765pub fn read_xml(
767 filename: impl AsRef<Path>,
768) -> Result<xml::XMLReader<bzip2::read::MultiBzDecoder<std::fs::File>>> {
769 xml::from_filename_bz2(filename)
770}