osm_pbf_iter 0.2.2

Parse OpenStreetMap .pbf dumps while trying to avoid copying
Documentation
use crate::{delta::DeltaEncodedIter, info::Info, primitive_block::PrimitiveBlock};
use protobuf_iter::*;

pub struct DenseInfoParser<'a> {
    primitive_block: &'a PrimitiveBlock<'a>,
    versions: PackedIter<'a, PackedVarint, u32>,
    timestamps: DeltaEncodedIter<'a, PackedVarint, i64>,
    changesets: DeltaEncodedIter<'a, PackedVarint, i64>,
    uids: DeltaEncodedIter<'a, PackedVarint, i32>,
    user_sids: DeltaEncodedIter<'a, PackedVarint, i32>,
    visibles: Option<PackedIter<'a, PackedVarint, u32>>,
}

macro_rules! some {
    ($e: expr) => {
        match $e {
            Some(x) => x,
            None => return None,
        }
    };
}

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

        Some(DenseInfoParser {
            primitive_block,
            versions: some!(iter.clone().tag::<ParseValue<'a>>(1).nth(0)).packed_varints(),
            timestamps: DeltaEncodedIter::new(some!(iter.clone().tag::<ParseValue<'a>>(2).nth(0))),
            changesets: DeltaEncodedIter::new(some!(iter.clone().tag::<ParseValue<'a>>(3).nth(0))),
            uids: DeltaEncodedIter::new(some!(iter.clone().tag::<ParseValue<'a>>(4).nth(0))),
            user_sids: DeltaEncodedIter::new(some!(iter.clone().tag::<ParseValue<'a>>(5).nth(0))),
            visibles: iter
                .clone()
                .tag::<ParseValue<'a>>(6)
                .nth(0)
                .map(|value| value.packed_varints()),
        })
    }
}

impl<'a> Iterator for DenseInfoParser<'a> {
    type Item = Info<'a>;

    fn next(&mut self) -> Option<Self::Item> {
        Some(Info {
            version: self.versions.next(),
            timestamp: self
                .timestamps
                .next()
                .map(|timestamp| self.primitive_block.convert_date(timestamp as u64)),
            changeset: self.changesets.next().map(|changesets| changesets as u64),
            uid: self.uids.next().map(|uid| uid as u32),
            user: self
                .user_sids
                .next()
                .map(|user_sid| self.primitive_block.stringtable[user_sid as usize]),
            visible: self
                .visibles
                .as_mut()
                .and_then(|visibles| visibles.next())
                .map(|visible| visible != 0),
        })
    }
}