use crate::block::{get_stringtable_key_value, str_from_stringtable};
use crate::dense::DenseNode;
use crate::error::Result;
use crate::proto::osmformat;
use crate::proto::osmformat::PrimitiveBlock;
use osmformat::relation::MemberType;
use protobuf::EnumOrUnknown;
#[derive(Clone, Debug)]
pub enum Element<'a> {
Node(Node<'a>),
DenseNode(DenseNode<'a>),
Way(Way<'a>),
Relation(Relation<'a>),
}
#[derive(Clone, Debug)]
pub struct Node<'a> {
block: &'a PrimitiveBlock,
osmnode: &'a osmformat::Node,
}
impl<'a> Node<'a> {
pub(crate) fn new(block: &'a PrimitiveBlock, osmnode: &'a osmformat::Node) -> Node<'a> {
Node { block, osmnode }
}
pub fn id(&self) -> i64 {
self.osmnode.id()
}
pub fn tags(&self) -> TagIter<'a> {
TagIter {
block: self.block,
key_indices: self.osmnode.keys.iter(),
val_indices: self.osmnode.vals.iter(),
}
}
pub fn info(&self) -> Info<'a> {
Info::new(self.block, self.osmnode.info.get_or_default())
}
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.osmnode.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.osmnode.lon()
}
pub fn decimicro_lon(&self) -> i32 {
(self.nano_lon() / 100) as i32
}
pub fn raw_tags(&self) -> RawTagIter<'a> {
RawTagIter {
key_indices: self.osmnode.keys.iter(),
val_indices: self.osmnode.vals.iter(),
}
}
pub fn raw_stringtable(&self) -> &[Vec<u8>] {
self.block.stringtable.s.as_slice()
}
}
#[derive(Clone, Debug)]
pub struct Way<'a> {
block: &'a PrimitiveBlock,
osmway: &'a osmformat::Way,
}
impl<'a> Way<'a> {
pub(crate) fn new(block: &'a PrimitiveBlock, osmway: &'a osmformat::Way) -> Way<'a> {
Way { block, osmway }
}
pub fn id(&self) -> i64 {
self.osmway.id()
}
pub fn tags(&self) -> TagIter<'a> {
TagIter {
block: self.block,
key_indices: self.osmway.keys.iter(),
val_indices: self.osmway.vals.iter(),
}
}
pub fn info(&self) -> Info<'a> {
Info::new(self.block, self.osmway.info.get_or_default())
}
pub fn refs(&self) -> WayRefIter<'a> {
WayRefIter {
deltas: self.osmway.refs.iter(),
current: 0,
}
}
pub fn node_locations(&self) -> WayNodeLocationsIter<'a> {
WayNodeLocationsIter {
block: self.block,
dlats: self.osmway.lat.iter(),
dlons: self.osmway.lon.iter(),
clat: 0,
clon: 0,
}
}
pub fn raw_refs(&self) -> &[i64] {
self.osmway.refs.as_slice()
}
pub fn raw_tags(&self) -> RawTagIter<'a> {
RawTagIter {
key_indices: self.osmway.keys.iter(),
val_indices: self.osmway.vals.iter(),
}
}
pub fn raw_stringtable(&self) -> &[Vec<u8>] {
self.block.stringtable.s.as_slice()
}
}
#[derive(Clone, Debug)]
pub struct Relation<'a> {
block: &'a PrimitiveBlock,
osmrel: &'a osmformat::Relation,
}
impl<'a> Relation<'a> {
pub(crate) fn new(block: &'a PrimitiveBlock, osmrel: &'a osmformat::Relation) -> Relation<'a> {
Relation { block, osmrel }
}
pub fn id(&self) -> i64 {
self.osmrel.id()
}
pub fn tags(&self) -> TagIter<'a> {
TagIter {
block: self.block,
key_indices: self.osmrel.keys.iter(),
val_indices: self.osmrel.vals.iter(),
}
}
pub fn info(&self) -> Info<'a> {
Info::new(self.block, self.osmrel.info.get_or_default())
}
pub fn members(&self) -> RelMemberIter<'a> {
RelMemberIter::new(self.block, self.osmrel)
}
pub fn raw_tags(&self) -> RawTagIter<'a> {
RawTagIter {
key_indices: self.osmrel.keys.iter(),
val_indices: self.osmrel.vals.iter(),
}
}
pub fn raw_stringtable(&self) -> &[Vec<u8>] {
self.block.stringtable.s.as_slice()
}
}
#[derive(Clone, Debug)]
pub struct WayRefIter<'a> {
deltas: std::slice::Iter<'a, i64>,
current: i64,
}
impl Iterator for WayRefIter<'_> {
type Item = i64;
fn next(&mut self) -> Option<Self::Item> {
match self.deltas.next() {
Some(&d) => {
self.current += d;
Some(self.current)
}
None => None,
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.deltas.size_hint()
}
}
impl ExactSizeIterator for WayRefIter<'_> {}
pub struct WayNodeLocation {
lat: i64,
lon: i64,
}
impl WayNodeLocation {
pub fn lat(&self) -> f64 {
1e-9 * self.nano_lat() as f64
}
pub fn nano_lat(&self) -> i64 {
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.lon
}
pub fn decimicro_lon(&self) -> i32 {
(self.nano_lon() / 100) as i32
}
}
#[derive(Clone, Debug)]
pub struct WayNodeLocationsIter<'a> {
block: &'a osmformat::PrimitiveBlock,
dlats: std::slice::Iter<'a, i64>,
dlons: std::slice::Iter<'a, i64>,
clat: i64,
clon: i64,
}
impl Iterator for WayNodeLocationsIter<'_> {
type Item = WayNodeLocation;
fn next(&mut self) -> Option<Self::Item> {
match (self.dlats.next(), self.dlons.next()) {
(Some(&dlat), Some(&dlon)) => {
self.clat += dlat;
self.clon += dlon;
Some(WayNodeLocation {
lat: self.block.lat_offset() + i64::from(self.block.granularity()) * self.clat,
lon: self.block.lon_offset() + i64::from(self.block.granularity()) * self.clon,
})
}
_ => None,
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.dlats.size_hint()
}
}
impl ExactSizeIterator for WayNodeLocationsIter<'_> {}
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum RelMemberType {
Node,
Way,
Relation,
}
impl From<EnumOrUnknown<MemberType>> for RelMemberType {
fn from(rmt: EnumOrUnknown<MemberType>) -> RelMemberType {
match rmt.unwrap() {
MemberType::NODE => RelMemberType::Node,
MemberType::WAY => RelMemberType::Way,
MemberType::RELATION => RelMemberType::Relation,
}
}
}
#[derive(Clone, Debug)]
pub struct RelMember<'a> {
block: &'a PrimitiveBlock,
pub role_sid: i32,
pub member_id: i64,
pub member_type: RelMemberType,
}
impl<'a> RelMember<'a> {
pub fn role(&self) -> Result<&'a str> {
str_from_stringtable(self.block, self.role_sid as usize)
}
}
#[derive(Clone, Debug)]
pub struct RelMemberIter<'a> {
block: &'a PrimitiveBlock,
role_sids: std::slice::Iter<'a, i32>,
member_id_deltas: std::slice::Iter<'a, i64>,
member_types: std::slice::Iter<'a, EnumOrUnknown<MemberType>>,
current_member_id: i64,
}
impl<'a> RelMemberIter<'a> {
fn new(block: &'a PrimitiveBlock, osmrel: &'a osmformat::Relation) -> RelMemberIter<'a> {
RelMemberIter {
block,
role_sids: osmrel.roles_sid.iter(),
member_id_deltas: osmrel.memids.iter(),
member_types: osmrel.types.iter(),
current_member_id: 0,
}
}
}
impl<'a> Iterator for RelMemberIter<'a> {
type Item = RelMember<'a>;
fn next(&mut self) -> Option<Self::Item> {
match (
self.role_sids.next(),
self.member_id_deltas.next(),
self.member_types.next(),
) {
(Some(role_sid), Some(mem_id_delta), Some(member_type)) => {
self.current_member_id += *mem_id_delta;
Some(RelMember {
block: self.block,
role_sid: *role_sid,
member_id: self.current_member_id,
member_type: RelMemberType::from(*member_type),
})
}
_ => None,
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.role_sids.size_hint()
}
}
impl ExactSizeIterator for RelMemberIter<'_> {}
#[derive(Clone, Debug)]
pub struct TagIter<'a> {
block: &'a PrimitiveBlock,
key_indices: std::slice::Iter<'a, u32>,
val_indices: std::slice::Iter<'a, u32>,
}
impl<'a> Iterator for TagIter<'a> {
type Item = (&'a str, &'a str);
fn next(&mut self) -> Option<Self::Item> {
get_stringtable_key_value(
self.block,
self.key_indices.next().map(|v| *v as usize),
self.val_indices.next().map(|v| *v as usize),
)
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.key_indices.size_hint()
}
}
impl ExactSizeIterator for TagIter<'_> {}
#[derive(Clone, Debug)]
pub struct RawTagIter<'a> {
key_indices: std::slice::Iter<'a, u32>,
val_indices: std::slice::Iter<'a, u32>,
}
impl Iterator for RawTagIter<'_> {
type Item = (u32, u32);
fn next(&mut self) -> Option<Self::Item> {
match (self.key_indices.next(), self.val_indices.next()) {
(Some(&key_index), Some(&val_index)) => Some((key_index, val_index)),
_ => None,
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.key_indices.size_hint()
}
}
impl ExactSizeIterator for RawTagIter<'_> {}
#[derive(Clone, Debug)]
pub struct Info<'a> {
block: &'a PrimitiveBlock,
info: &'a osmformat::Info,
}
impl<'a> Info<'a> {
fn new(block: &'a PrimitiveBlock, info: &'a osmformat::Info) -> Info<'a> {
Info { block, info }
}
pub fn version(&self) -> Option<i32> {
self.info.version
}
pub fn milli_timestamp(&self) -> Option<i64> {
if self.info.has_timestamp() {
Some(self.info.timestamp() * i64::from(self.block.date_granularity()))
} else {
None
}
}
pub fn changeset(&self) -> Option<i64> {
self.info.changeset
}
pub fn uid(&self) -> Option<i32> {
self.info.uid
}
pub fn user(&self) -> Option<Result<&'a str>> {
if self.info.has_user_sid() {
Some(str_from_stringtable(
self.block,
self.info.user_sid() as usize,
))
} else {
None
}
}
pub fn visible(&self) -> bool {
self.info.visible.unwrap_or(true)
}
pub fn deleted(&self) -> bool {
!self.visible()
}
}