use crate::block::{get_stringtable_key_value, str_from_stringtable};
use crate::error::Result;
use crate::proto::osmformat;
use std;
#[derive(Clone, Debug)]
pub struct DenseNode<'a> {
block: &'a osmformat::PrimitiveBlock,
pub id: i64,
lat: i64,
lon: i64,
keys_vals_indices: &'a [i32],
info: Option<DenseNodeInfo<'a>>,
}
impl<'a> DenseNode<'a> {
pub fn id(&self) -> i64 {
self.id
}
pub fn info(&'a self) -> Option<&'a DenseNodeInfo<'a>> {
self.info.as_ref()
}
pub fn lat(&self) -> f64 {
1e-9 * self.nano_lat() as f64
}
pub fn nano_lat(&self) -> i64 {
self.block.lat_offset() + i64::from(self.block.granularity()) * self.lat
}
pub fn decimicro_lat(&self) -> i32 {
(self.nano_lat() / 100) as i32
}
pub fn lon(&self) -> f64 {
1e-9 * self.nano_lon() as f64
}
pub fn nano_lon(&self) -> i64 {
self.block.lon_offset() + i64::from(self.block.granularity()) * self.lon
}
pub fn decimicro_lon(&self) -> i32 {
(self.nano_lon() / 100) as i32
}
pub fn tags(&self) -> DenseTagIter<'a> {
DenseTagIter {
block: self.block,
keys_vals_indices: self.keys_vals_indices.iter(),
}
}
pub fn raw_tags(&self) -> DenseRawTagIter<'a> {
DenseRawTagIter {
keys_vals_indices: self.keys_vals_indices.iter(),
}
}
}
#[derive(Clone, Debug)]
pub struct DenseNodeIter<'a> {
block: &'a osmformat::PrimitiveBlock,
dids: std::slice::Iter<'a, i64>, cid: i64, dlats: std::slice::Iter<'a, i64>, clat: i64,
dlons: std::slice::Iter<'a, i64>, clon: i64,
keys_vals_slice: &'a [i32],
keys_vals_index: usize,
info_iter: Option<DenseNodeInfoIter<'a>>,
}
impl<'a> DenseNodeIter<'a> {
pub(crate) fn new(
block: &'a osmformat::PrimitiveBlock,
osmdense: &'a osmformat::DenseNodes,
) -> DenseNodeIter<'a> {
let info_iter = Some(DenseNodeInfoIter::new(
block,
osmdense.denseinfo.get_or_default(),
));
DenseNodeIter {
block,
dids: osmdense.id.iter(),
cid: 0,
dlats: osmdense.lat.iter(),
clat: 0,
dlons: osmdense.lon.iter(),
clon: 0,
keys_vals_slice: osmdense.keys_vals.as_slice(),
keys_vals_index: 0,
info_iter,
}
}
pub(crate) fn empty(block: &'a osmformat::PrimitiveBlock) -> DenseNodeIter<'a> {
DenseNodeIter {
block,
dids: [].iter(),
cid: 0,
dlats: [].iter(),
clat: 0,
dlons: [].iter(),
clon: 0,
keys_vals_slice: &[],
keys_vals_index: 0,
info_iter: None,
}
}
}
impl<'a> Iterator for DenseNodeIter<'a> {
type Item = DenseNode<'a>;
fn next(&mut self) -> Option<Self::Item> {
match (
self.dids.next(),
self.dlats.next(),
self.dlons.next(),
self.info_iter.as_mut().and_then(|iter| iter.next()),
) {
(Some(did), Some(dlat), Some(dlon), info) => {
self.cid += *did;
self.clat += *dlat;
self.clon += *dlon;
let start_index = self.keys_vals_index;
let mut end_index = start_index;
for chunk in self.keys_vals_slice[self.keys_vals_index..].chunks(2) {
if chunk[0] != 0 && chunk.len() == 2 {
end_index += 2;
self.keys_vals_index += 2;
} else {
self.keys_vals_index += 1;
break;
}
}
Some(DenseNode {
block: self.block,
id: self.cid,
lat: self.clat,
lon: self.clon,
keys_vals_indices: &self.keys_vals_slice[start_index..end_index],
info,
})
}
_ => None,
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.dids.size_hint()
}
}
impl ExactSizeIterator for DenseNodeIter<'_> {}
#[derive(Clone, Debug)]
pub struct DenseNodeInfo<'a> {
block: &'a osmformat::PrimitiveBlock,
version: i32,
timestamp: i64,
changeset: i64,
uid: i32,
user_sid: i32,
visible: bool,
}
impl<'a> DenseNodeInfo<'a> {
pub fn version(&self) -> i32 {
self.version
}
pub fn changeset(&self) -> i64 {
self.changeset
}
pub fn uid(&self) -> i32 {
self.uid
}
pub fn user(&self) -> Result<&'a str> {
str_from_stringtable(self.block, self.user_sid as usize)
}
pub fn milli_timestamp(&self) -> i64 {
self.timestamp * i64::from(self.block.date_granularity())
}
pub fn visible(&self) -> bool {
self.visible
}
pub fn deleted(&self) -> bool {
!self.visible
}
}
#[derive(Clone, Debug)]
pub struct DenseNodeInfoIter<'a> {
block: &'a osmformat::PrimitiveBlock,
versions: std::slice::Iter<'a, i32>,
dtimestamps: std::slice::Iter<'a, i64>, ctimestamp: i64,
dchangesets: std::slice::Iter<'a, i64>, cchangeset: i64,
duids: std::slice::Iter<'a, i32>, cuid: i32,
duser_sids: std::slice::Iter<'a, i32>, cuser_sid: i32,
visible: std::slice::Iter<'a, bool>,
}
impl<'a> DenseNodeInfoIter<'a> {
fn new(
block: &'a osmformat::PrimitiveBlock,
info: &'a osmformat::DenseInfo,
) -> DenseNodeInfoIter<'a> {
DenseNodeInfoIter {
block,
versions: info.version.iter(),
dtimestamps: info.timestamp.iter(),
ctimestamp: 0,
dchangesets: info.changeset.iter(),
cchangeset: 0,
duids: info.uid.iter(),
cuid: 0,
duser_sids: info.user_sid.iter(),
cuser_sid: 0,
visible: info.visible.iter(),
}
}
}
impl<'a> Iterator for DenseNodeInfoIter<'a> {
type Item = DenseNodeInfo<'a>;
fn next(&mut self) -> Option<Self::Item> {
match (
self.versions.next(),
self.dtimestamps.next(),
self.dchangesets.next(),
self.duids.next(),
self.duser_sids.next(),
self.visible.next(),
) {
(
Some(&version),
Some(dtimestamp),
Some(dchangeset),
Some(duid),
Some(duser_sid),
visible_opt,
) => {
self.ctimestamp += *dtimestamp;
self.cchangeset += *dchangeset;
self.cuid += *duid;
self.cuser_sid += *duser_sid;
Some(DenseNodeInfo {
block: self.block,
version,
timestamp: self.ctimestamp,
changeset: self.cchangeset,
uid: self.cuid,
user_sid: self.cuser_sid,
visible: *visible_opt.unwrap_or(&true),
})
}
_ => None,
}
}
}
#[derive(Clone, Debug)]
pub struct DenseTagIter<'a> {
block: &'a osmformat::PrimitiveBlock,
keys_vals_indices: std::slice::Iter<'a, i32>,
}
impl<'a> Iterator for DenseTagIter<'a> {
type Item = (&'a str, &'a str);
fn next(&mut self) -> Option<Self::Item> {
get_stringtable_key_value(
self.block,
self.keys_vals_indices.next().map(|v| *v as usize),
self.keys_vals_indices.next().map(|v| *v as usize),
)
}
fn size_hint(&self) -> (usize, Option<usize>) {
let len = self.keys_vals_indices.len() / 2;
(len, Some(len))
}
}
impl ExactSizeIterator for DenseTagIter<'_> {}
#[derive(Clone, Debug)]
pub struct DenseRawTagIter<'a> {
keys_vals_indices: std::slice::Iter<'a, i32>,
}
impl Iterator for DenseRawTagIter<'_> {
type Item = (i32, i32);
fn next(&mut self) -> Option<Self::Item> {
match (self.keys_vals_indices.next(), self.keys_vals_indices.next()) {
(Some(&key_index), Some(&val_index)) => Some((key_index, val_index)),
_ => None,
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let len = self.keys_vals_indices.len() / 2;
(len, Some(len))
}
}
impl ExactSizeIterator for DenseRawTagIter<'_> {}