Skip to content

Commit 16eb6ff

Browse files
authored
feat: add iter_<xxx> for node/way/relation (#51)
1 parent 275acc3 commit 16eb6ff

File tree

3 files changed

+140
-23
lines changed

3 files changed

+140
-23
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "osmpbfreader"
3-
version = "0.17.0"
3+
version = "0.18.0"
44
authors = ["Guillaume Pinot <[email protected]>"]
55
description = "Read OpenStreetMap PBF files in rust."
66
documentation = "https://docs.rs/osmpbfreader"

src/blobs.rs

Lines changed: 46 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9,39 +9,49 @@
99
1010
use std::iter;
1111

12-
use crate::blocks;
13-
use crate::blocks::OsmObjs as OsmBlockObjs;
12+
use crate::blocks::{self, OsmObjs as OsmBlockObjs, Relations as BlockRelations, Ways as BlockWays, Nodes as BlockNodes};
1413
use crate::fileformat::Blob;
1514
use crate::objects::OsmObj;
1615
use crate::osmformat::PrimitiveBlock;
1716

17+
macro_rules! wrap {
18+
($name: ident, $wrap_type: ident => $inner_type: path) => {
1819
self_cell::self_cell!(
19-
struct OsmBlobObjs {
20+
#[allow(missing_docs)]
21+
pub struct $name {
2022
owner: PrimitiveBlock,
2123

2224
#[covariant]
23-
dependent: OsmBlockObjs,
25+
dependent: $wrap_type,
2426
}
2527
);
2628

27-
impl Iterator for OsmBlobObjs {
28-
type Item = OsmObj;
29+
impl Iterator for $name {
30+
type Item = $inner_type;
2931

3032
fn next(&mut self) -> Option<Self::Item> {
3133
self.with_dependent_mut(|_, objs| objs.next())
3234
}
3335
}
3436

37+
};
38+
}
39+
40+
wrap!(OsmBlobObjs, OsmBlockObjs => OsmObj);
41+
wrap!(OsmBlobRelations, BlockRelations => super::Relation);
42+
wrap!(OsmBlobWays, BlockWays => super::Way);
43+
wrap!(OsmBlobNodes, BlockNodes => super::Node);
44+
3545
/// An iterator on `Result<OsmObj>`.
36-
pub struct OsmObjs(OsmObjsImpl);
46+
pub struct OsmObjs<T: Iterator>(OsmObjsImpl<T>);
3747

38-
enum OsmObjsImpl {
39-
OkIter(iter::Map<OsmBlobObjs, fn(OsmObj) -> crate::Result<OsmObj>>),
40-
ErrIter(iter::Once<crate::Result<OsmObj>>),
48+
enum OsmObjsImpl<T: Iterator> {
49+
OkIter(iter::Map<T, fn(<T as Iterator>::Item) -> crate::Result<<T as Iterator>::Item>>),
50+
ErrIter(iter::Once<crate::Result<<T as Iterator>::Item>>),
4151
}
4252

43-
impl Iterator for OsmObjs {
44-
type Item = crate::Result<OsmObj>;
53+
impl<T: Iterator> Iterator for OsmObjs<T> {
54+
type Item = crate::Result<<T as Iterator>::Item>;
4555
fn next(&mut self) -> Option<Self::Item> {
4656
match self.0 {
4757
OsmObjsImpl::OkIter(ref mut iter) => iter.next(),
@@ -51,13 +61,33 @@ impl Iterator for OsmObjs {
5161
}
5262

5363
/// Transforms a `Result<blob>` into a `Iterator<Item = Result<OsmObj>>`.
54-
pub fn result_blob_into_iter(result: crate::Result<Blob>) -> OsmObjs {
64+
pub fn result_blob_into_iter(result: crate::Result<Blob>) -> OsmObjs<OsmBlobObjs> {
65+
match result.and_then(|b| crate::reader::primitive_block_from_blob(&b)) {
66+
Ok(block) => OsmObjs(OsmObjsImpl::OkIter(OsmBlobObjs::new(block, blocks::iter).map(Ok))),
67+
Err(e) => OsmObjs(OsmObjsImpl::ErrIter(iter::once(Err(e)))),
68+
}
69+
}
70+
71+
/// Transforms a `Result<blob>` into a `Iterator<Item = Result<Node>>`.
72+
pub fn result_blob_into_node_iter(result: crate::Result<Blob>) -> OsmObjs<OsmBlobNodes> {
5573
match result.and_then(|b| crate::reader::primitive_block_from_blob(&b)) {
56-
Ok(block) => OsmObjs(OsmObjsImpl::OkIter(new_rent_osm_objs(block).map(Ok))),
74+
Ok(block) => OsmObjs(OsmObjsImpl::OkIter(OsmBlobNodes::new(block, blocks::nodes).map(Ok))),
5775
Err(e) => OsmObjs(OsmObjsImpl::ErrIter(iter::once(Err(e)))),
5876
}
5977
}
6078

61-
fn new_rent_osm_objs(block: PrimitiveBlock) -> OsmBlobObjs {
62-
OsmBlobObjs::new(block, blocks::iter)
79+
/// Transforms a `Result<blob>` into a `Iterator<Item = Result<Way>>`.
80+
pub fn result_blob_into_way_iter(result: crate::Result<Blob>) -> OsmObjs<OsmBlobWays> {
81+
match result.and_then(|b| crate::reader::primitive_block_from_blob(&b)) {
82+
Ok(block) => OsmObjs(OsmObjsImpl::OkIter(OsmBlobWays::new(block, blocks::ways).map(Ok))),
83+
Err(e) => OsmObjs(OsmObjsImpl::ErrIter(iter::once(Err(e)))),
84+
}
85+
}
86+
87+
/// Transforms a `Result<blob>` into a `Iterator<Item = Result<Relation>>`.
88+
pub fn result_blob_into_relation_iter(result: crate::Result<Blob>) -> OsmObjs<OsmBlobRelations> {
89+
match result.and_then(|b| crate::reader::primitive_block_from_blob(&b)) {
90+
Ok(block) => OsmObjs(OsmObjsImpl::OkIter(OsmBlobRelations::new(block, blocks::relations).map(Ok))),
91+
Err(e) => OsmObjs(OsmObjsImpl::ErrIter(iter::once(Err(e)))),
92+
}
6393
}

src/reader.rs

Lines changed: 93 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
//! Tools for reading a pbf file.
99
10-
use crate::blobs::{self, result_blob_into_iter};
10+
use crate::blobs;
1111
use crate::error::{Error, Result};
1212
use crate::fileformat::{Blob, BlobHeader};
1313
use crate::objects::{OsmId, OsmObj};
@@ -67,7 +67,7 @@ impl<R: io::Read> OsmPbfReader<R> {
6767
/// }
6868
/// ```
6969
pub fn iter(&mut self) -> Iter<R> {
70-
Iter(self.blobs().flat_map(result_blob_into_iter))
70+
Iter(self.blobs().flat_map(blobs::result_blob_into_iter))
7171
}
7272

7373
/// Returns a parallel iterator on the OsmObj of the pbf file.
@@ -85,9 +85,53 @@ impl<R: io::Read> OsmPbfReader<R> {
8585
/// }
8686
/// ```
8787
pub fn par_iter(&mut self) -> ParIter<'_, R> {
88-
ParIter(self.blobs().par_flat_map(result_blob_into_iter))
88+
ParIter(self.blobs().par_flat_map(blobs::result_blob_into_iter))
8989
}
9090

91+
/// Returns an iterator on the Node of the pbf file.
92+
pub fn iter_nodes(&mut self) -> NodeIter<R> {
93+
NodeIter(self.blobs().flat_map(blobs::result_blob_into_node_iter))
94+
}
95+
96+
/// Returns a parallel iterator on the Node of the pbf file.
97+
///
98+
/// Several threads decode in parallel the file. The memory and
99+
/// CPU usage are guaranteed to be bounded even if the caller stop
100+
/// consuming items.
101+
pub fn par_iter_nodes(&mut self) -> NodeParIter<'_, R> {
102+
NodeParIter(self.blobs().par_flat_map(blobs::result_blob_into_node_iter))
103+
}
104+
105+
/// Returns an iterator on the Way of the pbf file.
106+
pub fn iter_ways(&mut self) -> WayIter<R> {
107+
WayIter(self.blobs().flat_map(blobs::result_blob_into_way_iter))
108+
}
109+
110+
/// Returns a parallel iterator on the Way of the pbf file.
111+
///
112+
/// Several threads decode in parallel the file. The memory and
113+
/// CPU usage are guaranteed to be bounded even if the caller stop
114+
/// consuming items.
115+
pub fn par_iter_ways(&mut self) -> WayParIter<'_, R> {
116+
WayParIter(self.blobs().par_flat_map(blobs::result_blob_into_way_iter))
117+
}
118+
119+
/// Returns an iterator on the Relation of the pbf file.
120+
pub fn iter_relations(&mut self) -> RelationIter<R> {
121+
RelationIter(self.blobs().flat_map(blobs::result_blob_into_relation_iter))
122+
}
123+
124+
/// Returns a parallel iterator on the Relation of the pbf file.
125+
///
126+
/// Several threads decode in parallel the file. The memory and
127+
/// CPU usage are guaranteed to be bounded even if the caller stop
128+
/// consuming items.
129+
pub fn par_iter_relations(&mut self) -> RelationParIter<'_, R> {
130+
RelationParIter(self.blobs().par_flat_map(blobs::result_blob_into_relation_iter))
131+
}
132+
133+
134+
91135
/// Rewinds the pbf file to the begining.
92136
///
93137
/// Useful if you want to read several consecutive times the same
@@ -283,14 +327,57 @@ pub fn primitive_block_from_blob(blob: &Blob) -> Result<PrimitiveBlock> {
283327

284328
pub_iterator_type! {
285329
#[doc="Iterator on the `OsmObj` of the pbf file."]
286-
Iter['a, R] = iter::FlatMap<Blobs<'a, R>, blobs::OsmObjs, fn(Result<Blob>) -> blobs::OsmObjs>
330+
Iter['a, R] = iter::FlatMap<Blobs<'a, R>, blobs::OsmObjs<blobs::OsmBlobObjs>, fn(Result<Blob>) -> blobs::OsmObjs<blobs::OsmBlobObjs>>
287331
where R: io::Read + 'a
288332
}
289333

290334
pub_iterator_type! {
291335
#[doc="Parallel iterator on the `OsmObj` of the pbf file."]
292336
ParIter['a, R] = par_map::FlatMap<Blobs<'a, R>,
293-
blobs::OsmObjs,
294-
fn(Result<Blob>) -> blobs::OsmObjs>
337+
blobs::OsmObjs<blobs::OsmBlobObjs>,
338+
fn(Result<Blob>) -> blobs::OsmObjs<blobs::OsmBlobObjs>>
339+
where R: io::Read + 'a
340+
}
341+
342+
pub_iterator_type! {
343+
#[doc="Iterator on the `OsmObj` of the pbf file."]
344+
NodeIter['a, R] = iter::FlatMap<Blobs<'a, R>, blobs::OsmObjs<blobs::OsmBlobNodes>, fn(Result<Blob>) -> blobs::OsmObjs<blobs::OsmBlobNodes>>
345+
where R: io::Read + 'a
346+
}
347+
348+
pub_iterator_type! {
349+
#[doc="Parallel iterator on the `OsmObj` of the pbf file."]
350+
NodeParIter['a, R] = par_map::FlatMap<Blobs<'a, R>,
351+
blobs::OsmObjs<blobs::OsmBlobNodes>,
352+
fn(Result<Blob>) -> blobs::OsmObjs<blobs::OsmBlobNodes>>
353+
where R: io::Read + 'a
354+
}
355+
356+
pub_iterator_type! {
357+
#[doc="Iterator on the `OsmObj` of the pbf file."]
358+
WayIter['a, R] = iter::FlatMap<Blobs<'a, R>, blobs::OsmObjs<blobs::OsmBlobWays>, fn(Result<Blob>) -> blobs::OsmObjs<blobs::OsmBlobWays>>
359+
where R: io::Read + 'a
360+
}
361+
362+
pub_iterator_type! {
363+
#[doc="Parallel iterator on the `OsmObj` of the pbf file."]
364+
WayParIter['a, R] = par_map::FlatMap<Blobs<'a, R>,
365+
blobs::OsmObjs<blobs::OsmBlobWays>,
366+
fn(Result<Blob>) -> blobs::OsmObjs<blobs::OsmBlobWays>>
367+
where R: io::Read + 'a
368+
}
369+
370+
371+
pub_iterator_type! {
372+
#[doc="Iterator on the `OsmObj` of the pbf file."]
373+
RelationIter['a, R] = iter::FlatMap<Blobs<'a, R>, blobs::OsmObjs<blobs::OsmBlobRelations>, fn(Result<Blob>) -> blobs::OsmObjs<blobs::OsmBlobRelations>>
374+
where R: io::Read + 'a
375+
}
376+
377+
pub_iterator_type! {
378+
#[doc="Parallel iterator on the `OsmObj` of the pbf file."]
379+
RelationParIter['a, R] = par_map::FlatMap<Blobs<'a, R>,
380+
blobs::OsmObjs<blobs::OsmBlobRelations>,
381+
fn(Result<Blob>) -> blobs::OsmObjs<blobs::OsmBlobRelations>>
295382
where R: io::Read + 'a
296383
}

0 commit comments

Comments
 (0)