osm_pbf_iter 0.2.2

Parse OpenStreetMap .pbf dumps while trying to avoid copying
Documentation
use crate::{
    Node, PrimitiveBlock, delimited::DelimitedIter, delta::DeltaEncodedIter,
    dense_info::DenseInfoParser,
};
use protobuf_iter::*;

pub struct DenseNodesParser<'a> {
    primitive_block: &'a PrimitiveBlock<'a>,
    ids: DeltaEncodedIter<'a, PackedVarint, i64>,
    lats: DeltaEncodedIter<'a, PackedVarint, i64>,
    lons: DeltaEncodedIter<'a, PackedVarint, i64>,
    infos: Option<DenseInfoParser<'a>>,
    keys_vals: DelimitedIter<'a, PackedVarint, u32>,
}

impl<'a> DenseNodesParser<'a> {
    pub fn new(primitive_block: &'a PrimitiveBlock<'a>, data: &'a [u8]) -> Option<Self> {
        let iter = MessageIter::new(data);

        Some(DenseNodesParser {
            primitive_block,
            ids: DeltaEncodedIter::new(iter.clone().tag::<ParseValue<'a>>(1).nth(0)?),
            lats: DeltaEncodedIter::new(iter.clone().tag::<ParseValue<'a>>(8).nth(0)?),
            lons: DeltaEncodedIter::new(iter.clone().tag::<ParseValue<'a>>(9).nth(0)?),
            infos: iter
                .clone()
                .tag::<ParseValue<'a>>(5)
                .nth(0)
                .and_then(|value| DenseInfoParser::new(primitive_block, *value)),
            keys_vals: DelimitedIter::new(iter.clone().tag::<ParseValue<'a>>(10).nth(0)?),
        })
    }
}

impl<'a> Iterator for DenseNodesParser<'a> {
    type Item = Node<'a>;

    fn next(&mut self) -> Option<Self::Item> {
        let mut keys_vals = self.keys_vals.next()?.into_iter();
        let tag_hint = keys_vals.size_hint().1.unwrap_or(keys_vals.size_hint().0);
        let mut tags = Vec::with_capacity(tag_hint);
        while let (Some(k), Some(v)) = (keys_vals.next(), keys_vals.next()) {
            let key = self.primitive_block.stringtable[k as usize];
            let val = self.primitive_block.stringtable[v as usize];
            tags.push((key, val));
        }

        let info = self.infos.as_mut().and_then(|infos| infos.next());

        Some(Node {
            id: self.ids.next()? as u64,
            lat: self.primitive_block.convert_lat(self.lats.next()?),
            lon: self.primitive_block.convert_lon(self.lons.next()?),
            info,
            tags,
        })
    }
}