diff --git a/src/groups.rs b/src/groups.rs index 5bfa03bd..8bd2d3cc 100644 --- a/src/groups.rs +++ b/src/groups.rs @@ -55,11 +55,25 @@ pub struct SimpleNodes<'a> { impl<'a> Iterator for SimpleNodes<'a> { type Item = Node; fn next(&mut self) -> Option { - self.iter.next().map(|n| Node { - id: NodeId(n.get_id()), - decimicro_lat: make_lat(n.get_lat(), self.block), - decimicro_lon: make_lon(n.get_lon(), self.block), - tags: make_tags(n.get_keys(), n.get_vals(), self.block), + self.iter.next().map(|n| { + let info = n.get_info(); + let info_timestamp = if info.has_timestamp() { + Some(info.get_timestamp()) + } else { + None + }; + let info_visible = if info.has_visible() { + Some(info.get_visible()) + } else { + None + }; + Node { + id: NodeId(n.get_id()), + decimicro_lat: make_lat(n.get_lat(), self.block), + decimicro_lon: make_lon(n.get_lon(), self.block), + tags: make_tags(n.get_keys(), n.get_vals(), self.block), + info: make_info(info_timestamp, info_visible), + } }) } fn size_hint(&self) -> (usize, Option) { @@ -69,13 +83,22 @@ impl<'a> Iterator for SimpleNodes<'a> { pub fn dense_nodes<'a>(group: &'a PrimitiveGroup, block: &'a PrimitiveBlock) -> DenseNodes<'a> { let dense = group.get_dense(); + let (dinfo_timestamp, dinfo_visible) = if dense.has_denseinfo() { + let dinfo = dense.get_denseinfo(); + (dinfo.get_timestamp().iter(), dinfo.get_visible().iter()) + } else { + ([].iter(), [].iter()) + }; DenseNodes { block, dids: dense.get_id().iter(), + dinfo_timestamp: dinfo_timestamp, + dinfo_visible: dinfo_visible, dlats: dense.get_lat().iter(), dlons: dense.get_lon().iter(), keys_vals: dense.get_keys_vals().iter(), cur_id: 0, + cur_info_timestamp: 0, cur_lat: 0, cur_lon: 0, } @@ -84,10 +107,13 @@ pub fn dense_nodes<'a>(group: &'a PrimitiveGroup, block: &'a PrimitiveBlock) -> pub struct DenseNodes<'a> { block: &'a PrimitiveBlock, dids: slice::Iter<'a, i64>, + dinfo_timestamp: slice::Iter<'a, i64>, + dinfo_visible: slice::Iter<'a, bool>, dlats: slice::Iter<'a, i64>, dlons: slice::Iter<'a, i64>, keys_vals: slice::Iter<'a, i32>, cur_id: i64, + cur_info_timestamp: i64, cur_lat: i64, cur_lon: i64, } @@ -116,11 +142,17 @@ impl<'a> Iterator for DenseNodes<'a> { tags.insert(k, v); } tags.shrink_to_fit(); + let info_timestamp = self.dinfo_timestamp.next().map(|ts| *ts); + if let Some(ts) = info_timestamp { + self.cur_info_timestamp += ts; + } + let info_visible = self.dinfo_visible.next().map(|ts| *ts); Some(Node { id: NodeId(self.cur_id), decimicro_lat: make_lat(self.cur_lat, self.block), decimicro_lon: make_lon(self.cur_lon, self.block), tags, + info: make_info(info_timestamp, info_visible), }) } } @@ -150,10 +182,22 @@ impl<'a> Iterator for Ways<'a> { NodeId(n) }) .collect(); + let info = w.get_info(); + let info_timestamp = if info.has_timestamp() { + Some(info.get_timestamp()) + } else { + None + }; + let info_visible = if info.has_visible() { + Some(info.get_visible()) + } else { + None + }; Way { id: WayId(w.get_id()), nodes, tags: make_tags(w.get_keys(), w.get_vals(), self.block), + info: make_info(info_timestamp, info_visible), } }) } @@ -196,10 +240,22 @@ impl<'a> Iterator for Relations<'a> { } }) .collect(); + let info = rel.get_info(); + let info_timestamp = if info.has_timestamp() { + Some(info.get_timestamp()) + } else { + None + }; + let info_visible = if info.has_visible() { + Some(info.get_visible()) + } else { + None + }; Relation { id: RelationId(rel.get_id()), refs, tags: make_tags(rel.get_keys(), rel.get_vals(), self.block), + info: make_info(info_timestamp, info_visible), } }) } @@ -235,3 +291,15 @@ fn make_tags(keys: &[u32], vals: &[u32], b: &PrimitiveBlock) -> Tags { tags.shrink_to_fit(); tags } + +fn make_info(timestamp: Option, visible: Option) -> Option { + if timestamp.is_some() || visible.is_some() { + Some(Info { + timestamp: timestamp, + // osmformat.proto somewhat sounds like true is a sensible default. + visible: visible.unwrap_or(true), + }) + } else { + None + } +} diff --git a/src/objects.rs b/src/objects.rs index 0a64cf12..76b02c4d 100644 --- a/src/objects.rs +++ b/src/objects.rs @@ -195,6 +195,8 @@ pub struct Node { pub decimicro_lat: i32, /// The longitude in decimicro degrees (10⁻⁷ degrees). pub decimicro_lon: i32, + /// The info of the node. + pub info: Option, } impl Node { @@ -219,6 +221,8 @@ pub struct Way { pub tags: Tags, /// The ordered list of nodes as id. pub nodes: Vec, + /// The info of the way. + pub info: Option, } impl Way { @@ -254,6 +258,18 @@ pub struct Relation { pub tags: Tags, /// Members of the relation. pub refs: Vec, + /// The info of the relation. + pub info: Option, +} + +/// An Info object for storing metadate about a Node, Way or Relation. +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Hash, Serialize, Deserialize)] +pub struct Info { + /// The timestamp when the object was introduced. + pub timestamp: Option, + /// Wether the object should be considered a currently valid object. Being false hints to it + /// being a historic version that is not uptodate anymore. Defaults to true. + pub visible: bool, } impl ::std::convert::From for OsmId {