A Rust library for reading the OpenStreetMap PBF file format (*.osm.pbf).

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542
  1. //! Nodes, ways and relations
  2. use error::Result;
  3. use block::str_from_stringtable;
  4. use dense::DenseNode;
  5. use proto::osmformat::PrimitiveBlock;
  6. use proto::osmformat;
  7. use std;
  8. /// An enum with the OSM core elements: nodes, ways and relations.
  9. #[derive(Clone, Debug)]
  10. pub enum Element<'a> {
  11. /// A node. Also, see `DenseNode`.
  12. Node(Node<'a>),
  13. /// Just like `Node`, but with a different representation in memory. This distinction is
  14. /// usually not important but is not abstracted away to avoid copying. So, if you want to match
  15. /// `Node`, you also likely want to match `DenseNode`.
  16. DenseNode(DenseNode<'a>),
  17. /// A way.
  18. Way(Way<'a>),
  19. /// A relation.
  20. Relation(Relation<'a>),
  21. }
  22. /// An OpenStreetMap node element (See [OSM wiki](http://wiki.openstreetmap.org/wiki/Node)).
  23. #[derive(Clone, Debug)]
  24. pub struct Node<'a> {
  25. block: &'a PrimitiveBlock,
  26. osmnode: &'a osmformat::Node,
  27. }
  28. impl<'a> Node<'a> {
  29. pub(crate) fn new(block: &'a PrimitiveBlock, osmnode: &'a osmformat::Node) -> Node<'a> {
  30. Node {
  31. block,
  32. osmnode,
  33. }
  34. }
  35. /// Returns the node id. It should be unique between nodes and might be negative to indicate
  36. /// that the element has not yet been uploaded to a server.
  37. pub fn id(&self) -> i64 {
  38. self.osmnode.get_id()
  39. }
  40. /// Returns an iterator over the tags of this node
  41. /// (See [OSM wiki](http://wiki.openstreetmap.org/wiki/Tags)).
  42. /// A tag is represented as a pair of strings (key and value).
  43. ///
  44. /// # Example
  45. /// ```
  46. /// use osmpbf::*;
  47. ///
  48. /// # fn foo() -> Result<()> {
  49. /// let reader = ElementReader::from_path("tests/test.osm.pbf")?;
  50. ///
  51. /// reader.for_each(|element| {
  52. /// if let Element::Node(node) = element {
  53. /// for (key, value) in node.tags() {
  54. /// println!("key: {}, value: {}", key, value);
  55. /// }
  56. /// }
  57. /// })?;
  58. ///
  59. /// # Ok(())
  60. /// # }
  61. /// ```
  62. pub fn tags(&self) -> TagIter<'a> {
  63. TagIter {
  64. block: self.block,
  65. key_indices: self.osmnode.get_keys().iter(),
  66. val_indices: self.osmnode.get_vals().iter(),
  67. }
  68. }
  69. /// Returns additional metadata for this element.
  70. pub fn info(&self) -> Info<'a> {
  71. Info::new(self.block, self.osmnode.get_info())
  72. }
  73. /// Returns the latitude coordinate in degrees.
  74. pub fn lat(&self) -> f64 {
  75. 0.000_000_001_f64 * (self.block.get_lat_offset() +
  76. (i64::from(self.block.get_granularity()) *
  77. self.osmnode.get_lat())) as f64
  78. }
  79. /// Returns the longitude coordinate in degrees.
  80. pub fn lon(&self) -> f64 {
  81. 0.000_000_001_f64 * (self.block.get_lon_offset() +
  82. (i64::from(self.block.get_granularity()) *
  83. self.osmnode.get_lon())) as f64
  84. }
  85. /// Returns an iterator over the tags of this node
  86. /// (See [OSM wiki](http://wiki.openstreetmap.org/wiki/Tags)).
  87. /// A tag is represented as a pair of indices (key and value) to the stringtable of the current
  88. /// `PrimitiveBlock`.
  89. pub fn raw_tags(&self) -> RawTagIter<'a> {
  90. RawTagIter {
  91. block: self.block,
  92. key_indices: self.osmnode.get_keys().iter(),
  93. val_indices: self.osmnode.get_vals().iter(),
  94. }
  95. }
  96. /// Returns the raw stringtable. Elements in a `PrimitiveBlock` do not store strings
  97. /// themselves; instead, they just store indices to a common stringtable. By convention, the
  98. /// contained strings are UTF-8 encoded but it is not safe to assume that (use
  99. /// `std::str::from_utf8`).
  100. pub fn raw_stringtable(&self) -> &[Vec<u8>] {
  101. self.block.get_stringtable().get_s()
  102. }
  103. }
  104. /// An OpenStreetMap way element (See [OSM wiki](http://wiki.openstreetmap.org/wiki/Way)).
  105. ///
  106. /// A way contains an ordered list of node references that can be accessed with the `refs` or the
  107. /// `refs_slice` method.
  108. #[derive(Clone, Debug)]
  109. pub struct Way<'a> {
  110. block: &'a PrimitiveBlock,
  111. osmway: &'a osmformat::Way,
  112. }
  113. impl<'a> Way<'a> {
  114. pub(crate) fn new(block: &'a PrimitiveBlock, osmway: &'a osmformat::Way) -> Way<'a> {
  115. Way {
  116. block,
  117. osmway,
  118. }
  119. }
  120. /// Returns the way id.
  121. pub fn id(&self) -> i64 {
  122. self.osmway.get_id()
  123. }
  124. /// Returns an iterator over the tags of this way
  125. /// (See [OSM wiki](http://wiki.openstreetmap.org/wiki/Tags)).
  126. /// A tag is represented as a pair of strings (key and value).
  127. ///
  128. /// # Example
  129. /// ```
  130. /// use osmpbf::*;
  131. ///
  132. /// # fn foo() -> Result<()> {
  133. /// let reader = ElementReader::from_path("tests/test.osm.pbf")?;
  134. ///
  135. /// reader.for_each(|element| {
  136. /// if let Element::Way(way) = element {
  137. /// for (key, value) in way.tags() {
  138. /// println!("key: {}, value: {}", key, value);
  139. /// }
  140. /// }
  141. /// })?;
  142. ///
  143. /// # Ok(())
  144. /// # }
  145. /// ```
  146. pub fn tags(&self) -> TagIter<'a> {
  147. TagIter {
  148. block: self.block,
  149. key_indices: self.osmway.get_keys().iter(),
  150. val_indices: self.osmway.get_vals().iter(),
  151. }
  152. }
  153. /// Returns additional metadata for this element.
  154. pub fn info(&self) -> Info<'a> {
  155. Info::new(self.block, self.osmway.get_info())
  156. }
  157. /// Returns an iterator over the references of this way. Each reference should correspond to a
  158. /// node id.
  159. pub fn refs(&self) -> WayRefIter<'a> {
  160. WayRefIter {
  161. deltas: self.osmway.get_refs().iter(),
  162. current: 0,
  163. }
  164. }
  165. /// Returns a slice of references. Each reference should correspond to a node id.
  166. pub fn refs_slice(&self) -> &[i64] {
  167. self.osmway.get_refs()
  168. }
  169. /// Returns an iterator over the tags of this way
  170. /// (See [OSM wiki](http://wiki.openstreetmap.org/wiki/Tags)).
  171. /// A tag is represented as a pair of indices (key and value) to the stringtable of the current
  172. /// `PrimitiveBlock`.
  173. pub fn raw_tags(&self) -> RawTagIter<'a> {
  174. RawTagIter {
  175. block: self.block,
  176. key_indices: self.osmway.get_keys().iter(),
  177. val_indices: self.osmway.get_vals().iter(),
  178. }
  179. }
  180. /// Returns the raw stringtable. Elements in a `PrimitiveBlock` do not store strings
  181. /// themselves; instead, they just store indices to a common stringtable. By convention, the
  182. /// contained strings are UTF-8 encoded but it is not safe to assume that (use
  183. /// `std::str::from_utf8`).
  184. pub fn raw_stringtable(&self) -> &[Vec<u8>] {
  185. self.block.get_stringtable().get_s()
  186. }
  187. }
  188. /// An OpenStreetMap relation element (See [OSM wiki](http://wiki.openstreetmap.org/wiki/Relation)).
  189. ///
  190. /// A relation contains an ordered list of members that can be of any element type.
  191. #[derive(Clone, Debug)]
  192. pub struct Relation<'a> {
  193. block: &'a PrimitiveBlock,
  194. osmrel: &'a osmformat::Relation,
  195. }
  196. impl<'a> Relation<'a> {
  197. pub(crate) fn new(block: &'a PrimitiveBlock, osmrel: &'a osmformat::Relation) -> Relation<'a> {
  198. Relation {
  199. block,
  200. osmrel,
  201. }
  202. }
  203. /// Returns the relation id.
  204. pub fn id(&self) -> i64 {
  205. self.osmrel.get_id()
  206. }
  207. /// Returns an iterator over the tags of this relation
  208. /// (See [OSM wiki](http://wiki.openstreetmap.org/wiki/Tags)).
  209. /// A tag is represented as a pair of strings (key and value).
  210. ///
  211. /// # Example
  212. /// ```
  213. /// use osmpbf::*;
  214. ///
  215. /// # fn foo() -> Result<()> {
  216. /// let reader = ElementReader::from_path("tests/test.osm.pbf")?;
  217. ///
  218. /// reader.for_each(|element| {
  219. /// if let Element::Relation(relation) = element {
  220. /// for (key, value) in relation.tags() {
  221. /// println!("key: {}, value: {}", key, value);
  222. /// }
  223. /// }
  224. /// })?;
  225. ///
  226. /// # Ok(())
  227. /// # }
  228. /// ```
  229. pub fn tags(&self) -> TagIter<'a> {
  230. TagIter {
  231. block: self.block,
  232. key_indices: self.osmrel.get_keys().iter(),
  233. val_indices: self.osmrel.get_vals().iter(),
  234. }
  235. }
  236. /// Returns additional metadata for this element.
  237. pub fn info(&self) -> Info<'a> {
  238. Info::new(self.block, self.osmrel.get_info())
  239. }
  240. /// Returns an iterator over the members of this relation.
  241. pub fn members(&self) -> RelMemberIter<'a> {
  242. RelMemberIter::new(self.block, self.osmrel)
  243. }
  244. /// Returns an iterator over the tags of this relation
  245. /// (See [OSM wiki](http://wiki.openstreetmap.org/wiki/Tags)).
  246. /// A tag is represented as a pair of indices (key and value) to the stringtable of the current
  247. /// `PrimitiveBlock`.
  248. pub fn raw_tags(&self) -> RawTagIter<'a> {
  249. RawTagIter {
  250. block: self.block,
  251. key_indices: self.osmrel.get_keys().iter(),
  252. val_indices: self.osmrel.get_vals().iter(),
  253. }
  254. }
  255. /// Returns the raw stringtable. Elements in a `PrimitiveBlock` do not store strings
  256. /// themselves; instead, they just store indices to a common stringtable. By convention, the
  257. /// contained strings are UTF-8 encoded but it is not safe to assume that (use
  258. /// `std::str::from_utf8`).
  259. pub fn raw_stringtable(&self) -> &[Vec<u8>] {
  260. self.block.get_stringtable().get_s()
  261. }
  262. }
  263. /// An iterator over the references of a way.
  264. ///
  265. /// Each reference corresponds to a node id.
  266. #[derive(Clone, Debug)]
  267. pub struct WayRefIter<'a> {
  268. deltas: std::slice::Iter<'a, i64>,
  269. current: i64,
  270. }
  271. impl<'a> Iterator for WayRefIter<'a> {
  272. type Item = i64;
  273. fn next(&mut self) -> Option<Self::Item> {
  274. match self.deltas.next() {
  275. Some(&d) => {
  276. self.current += d;
  277. Some(self.current)
  278. },
  279. None => None,
  280. }
  281. }
  282. fn size_hint(&self) -> (usize, Option<usize>) {
  283. self.deltas.size_hint()
  284. }
  285. }
  286. impl<'a> ExactSizeIterator for WayRefIter<'a> {}
  287. /// The element type of a relation member.
  288. #[derive(Clone, Debug, Eq, PartialEq)]
  289. pub enum RelMemberType {
  290. Node,
  291. Way,
  292. Relation
  293. }
  294. impl From<osmformat::Relation_MemberType> for RelMemberType {
  295. fn from(rmt: osmformat::Relation_MemberType) -> RelMemberType {
  296. match rmt {
  297. osmformat::Relation_MemberType::NODE => RelMemberType::Node,
  298. osmformat::Relation_MemberType::WAY => RelMemberType::Way,
  299. osmformat::Relation_MemberType::RELATION => RelMemberType::Relation,
  300. }
  301. }
  302. }
  303. //TODO encapsulate member_id based on member_type (NodeId, WayId, RelationId)
  304. /// A member of a relation.
  305. ///
  306. /// Each member has a member type and a member id that references an element of that type.
  307. #[derive(Clone, Debug)]
  308. pub struct RelMember<'a> {
  309. block: &'a PrimitiveBlock,
  310. pub role_sid: i32,
  311. pub member_id: i64,
  312. pub member_type: RelMemberType,
  313. }
  314. impl<'a> RelMember<'a> {
  315. /// Returns the role of a relation member.
  316. pub fn role(&self) -> Result<&'a str> {
  317. str_from_stringtable(self.block, self.role_sid as usize)
  318. }
  319. }
  320. /// An iterator over the members of a relation.
  321. #[derive(Clone, Debug)]
  322. pub struct RelMemberIter<'a> {
  323. block: &'a PrimitiveBlock,
  324. role_sids: std::slice::Iter<'a, i32>,
  325. member_id_deltas: std::slice::Iter<'a, i64>,
  326. member_types: std::slice::Iter<'a, osmformat::Relation_MemberType>,
  327. current_member_id: i64,
  328. }
  329. impl<'a> RelMemberIter<'a> {
  330. fn new(block: &'a PrimitiveBlock, osmrel: &'a osmformat::Relation) -> RelMemberIter<'a> {
  331. RelMemberIter {
  332. block,
  333. role_sids: osmrel.get_roles_sid().iter(),
  334. member_id_deltas: osmrel.get_memids().iter(),
  335. member_types: osmrel.get_types().iter(),
  336. current_member_id: 0,
  337. }
  338. }
  339. }
  340. impl<'a> Iterator for RelMemberIter<'a> {
  341. type Item = RelMember<'a>;
  342. fn next(&mut self) -> Option<Self::Item> {
  343. match (self.role_sids.next(),
  344. self.member_id_deltas.next(),
  345. self.member_types.next()) {
  346. (Some(role_sid), Some(mem_id_delta), Some(member_type)) => {
  347. self.current_member_id += *mem_id_delta;
  348. Some(RelMember {
  349. block: self.block,
  350. role_sid: *role_sid,
  351. member_id: self.current_member_id,
  352. member_type: RelMemberType::from(*member_type),
  353. })
  354. },
  355. _ => None,
  356. }
  357. }
  358. fn size_hint(&self) -> (usize, Option<usize>) {
  359. self.role_sids.size_hint()
  360. }
  361. }
  362. impl<'a> ExactSizeIterator for RelMemberIter<'a> {}
  363. /// An iterator over the tags of an element. It returns a pair of strings (key and value).
  364. #[derive(Clone, Debug)]
  365. pub struct TagIter<'a> {
  366. block: &'a PrimitiveBlock,
  367. key_indices: std::slice::Iter<'a, u32>,
  368. val_indices: std::slice::Iter<'a, u32>,
  369. }
  370. //TODO return Result?
  371. impl<'a> Iterator for TagIter<'a> {
  372. type Item = (&'a str, &'a str);
  373. fn next(&mut self) -> Option<Self::Item> {
  374. match (self.key_indices.next(), self.val_indices.next()) {
  375. (Some(&key_index), Some(&val_index)) => {
  376. let k_res = str_from_stringtable(self.block, key_index as usize);
  377. let v_res = str_from_stringtable(self.block, val_index as usize);
  378. if let (Ok(k), Ok(v)) = (k_res, v_res) {
  379. Some((k, v))
  380. } else {
  381. None
  382. }
  383. },
  384. _ => None,
  385. }
  386. }
  387. fn size_hint(&self) -> (usize, Option<usize>) {
  388. self.key_indices.size_hint()
  389. }
  390. }
  391. impl<'a> ExactSizeIterator for TagIter<'a> {}
  392. /// An iterator over the tags of an element. It returns a pair of indices (key and value) to the
  393. /// stringtable of the current `PrimitiveBlock`.
  394. #[derive(Clone, Debug)]
  395. pub struct RawTagIter<'a> {
  396. block: &'a PrimitiveBlock,
  397. key_indices: std::slice::Iter<'a, u32>,
  398. val_indices: std::slice::Iter<'a, u32>,
  399. }
  400. //TODO return Result?
  401. impl<'a> Iterator for RawTagIter<'a> {
  402. type Item = (u32, u32);
  403. fn next(&mut self) -> Option<Self::Item> {
  404. match (self.key_indices.next(), self.val_indices.next()) {
  405. (Some(&key_index), Some(&val_index)) => Some((key_index, val_index)),
  406. _ => None,
  407. }
  408. }
  409. fn size_hint(&self) -> (usize, Option<usize>) {
  410. self.key_indices.size_hint()
  411. }
  412. }
  413. impl<'a> ExactSizeIterator for RawTagIter<'a> {}
  414. /// Additional metadata that might be included in each element.
  415. #[derive(Clone, Debug)]
  416. pub struct Info<'a> {
  417. block: &'a PrimitiveBlock,
  418. info: &'a osmformat::Info,
  419. }
  420. impl<'a> Info<'a> {
  421. fn new(block: &'a PrimitiveBlock, info: &'a osmformat::Info) -> Info<'a> {
  422. Info {
  423. block,
  424. info,
  425. }
  426. }
  427. /// Returns the version of this element.
  428. pub fn version(&self) -> Option<i32> {
  429. if self.info.has_version() {
  430. Some(self.info.get_version())
  431. } else {
  432. None
  433. }
  434. }
  435. /// Returns the time stamp in milliseconds since the epoch.
  436. pub fn milli_timestamp(&self) -> Option<i64> {
  437. if self.info.has_timestamp() {
  438. Some(self.info.get_timestamp() * i64::from(self.block.get_date_granularity()))
  439. } else {
  440. None
  441. }
  442. }
  443. /// Returns the changeset id.
  444. pub fn changeset(&self) -> Option<i64> {
  445. if self.info.has_changeset() {
  446. Some(self.info.get_changeset())
  447. } else {
  448. None
  449. }
  450. }
  451. /// Returns the user id.
  452. pub fn uid(&self) -> Option<i32> {
  453. if self.info.has_uid() {
  454. Some(self.info.get_uid())
  455. } else {
  456. None
  457. }
  458. }
  459. /// Returns the user name.
  460. pub fn user(&self) -> Option<Result<&'a str>> {
  461. if self.info.has_user_sid() {
  462. Some(str_from_stringtable(self.block, self.info.get_user_sid() as usize))
  463. } else {
  464. None
  465. }
  466. }
  467. /// Returns the visibility status of an element. This is only relevant if the PBF file contains
  468. /// historical information.
  469. pub fn visible(&self) -> bool {
  470. if self.info.has_visible() {
  471. self.info.get_visible()
  472. } else {
  473. // If the visible flag is not present it must be assumed to be true.
  474. true
  475. }
  476. }
  477. }