use crate::dense::DenseNodeIter;
use crate::elements::{Element, Node, Relation, Way};
use crate::error::{new_error, ErrorKind, Result};
use crate::proto::osmformat;
use std;
#[derive(Clone, Debug)]
pub struct HeaderBlock {
header: osmformat::HeaderBlock,
}
impl HeaderBlock {
pub(crate) fn new(header: osmformat::HeaderBlock) -> HeaderBlock {
HeaderBlock { header }
}
pub fn bbox(&self) -> Option<HeaderBBox> {
self.header.bbox.as_ref().map(|bbox| HeaderBBox {
left: (bbox.left() as f64) * 1.0_e-9,
right: (bbox.right() as f64) * 1.0_e-9,
top: (bbox.top() as f64) * 1.0_e-9,
bottom: (bbox.bottom() as f64) * 1.0_e-9,
})
}
pub fn required_features(&self) -> &[String] {
self.header.required_features.as_slice()
}
pub fn optional_features(&self) -> &[String] {
self.header.optional_features.as_slice()
}
pub fn writing_program(&self) -> Option<&str> {
if self.header.has_writingprogram() {
Some(self.header.writingprogram())
} else {
None
}
}
pub fn source(&self) -> Option<&str> {
if self.header.has_source() {
Some(self.header.source())
} else {
None
}
}
pub fn osmosis_replication_timestamp(&self) -> Option<i64> {
if self.header.has_osmosis_replication_timestamp() {
Some(self.header.osmosis_replication_timestamp())
} else {
None
}
}
pub fn osmosis_replication_sequence_number(&self) -> Option<i64> {
if self.header.has_osmosis_replication_sequence_number() {
Some(self.header.osmosis_replication_sequence_number())
} else {
None
}
}
pub fn osmosis_replication_base_url(&self) -> Option<&str> {
if self.header.has_osmosis_replication_base_url() {
Some(self.header.osmosis_replication_base_url())
} else {
None
}
}
}
#[derive(Clone, Debug)]
pub struct HeaderBBox {
pub left: f64,
pub right: f64,
pub top: f64,
pub bottom: f64,
}
#[derive(Clone, Debug)]
pub struct PrimitiveBlock {
block: osmformat::PrimitiveBlock,
}
impl PrimitiveBlock {
pub(crate) fn new(block: osmformat::PrimitiveBlock) -> PrimitiveBlock {
PrimitiveBlock { block }
}
pub fn elements(&self) -> BlockElementsIter {
BlockElementsIter::new(&self.block)
}
pub fn groups(&self) -> GroupIter {
GroupIter::new(&self.block)
}
pub fn for_each_element<F>(&self, mut f: F)
where
F: for<'a> FnMut(Element<'a>),
{
for group in self.groups() {
for node in group.nodes() {
f(Element::Node(node))
}
for dnode in group.dense_nodes() {
f(Element::DenseNode(dnode))
}
for way in group.ways() {
f(Element::Way(way));
}
for relation in group.relations() {
f(Element::Relation(relation));
}
}
}
pub fn raw_stringtable(&self) -> &[Vec<u8>] {
self.block.stringtable.s.as_slice()
}
}
#[derive(Clone, Debug)]
pub struct PrimitiveGroup<'a> {
block: &'a osmformat::PrimitiveBlock,
group: &'a osmformat::PrimitiveGroup,
}
impl<'a> PrimitiveGroup<'a> {
fn new(
block: &'a osmformat::PrimitiveBlock,
group: &'a osmformat::PrimitiveGroup,
) -> PrimitiveGroup<'a> {
PrimitiveGroup { block, group }
}
pub fn nodes(&self) -> GroupNodeIter<'a> {
GroupNodeIter::new(self.block, self.group)
}
pub fn dense_nodes(&self) -> DenseNodeIter<'a> {
DenseNodeIter::new(self.block, self.group.dense.get_or_default())
}
pub fn ways(&self) -> GroupWayIter<'a> {
GroupWayIter::new(self.block, self.group)
}
pub fn relations(&self) -> GroupRelationIter<'a> {
GroupRelationIter::new(self.block, self.group)
}
}
#[derive(Clone, Debug)]
pub struct BlockElementsIter<'a> {
block: &'a osmformat::PrimitiveBlock,
state: ElementsIterState,
groups: std::slice::Iter<'a, osmformat::PrimitiveGroup>,
dense_nodes: DenseNodeIter<'a>,
nodes: std::slice::Iter<'a, osmformat::Node>,
ways: std::slice::Iter<'a, osmformat::Way>,
relations: std::slice::Iter<'a, osmformat::Relation>,
}
#[derive(Copy, Clone, Debug)]
enum ElementsIterState {
Group,
DenseNode,
Node,
Way,
Relation,
}
impl<'a> BlockElementsIter<'a> {
fn new(block: &'a osmformat::PrimitiveBlock) -> BlockElementsIter<'a> {
BlockElementsIter {
block,
state: ElementsIterState::Group,
groups: block.primitivegroup.iter(),
dense_nodes: DenseNodeIter::empty(block),
nodes: [].iter(),
ways: [].iter(),
relations: [].iter(),
}
}
#[inline]
#[allow(clippy::option_option)]
fn step(&mut self) -> Option<Option<Element<'a>>> {
match self.state {
ElementsIterState::Group => match self.groups.next() {
Some(group) => {
self.state = ElementsIterState::DenseNode;
self.dense_nodes = DenseNodeIter::new(self.block, group.dense.get_or_default());
self.nodes = group.nodes.iter();
self.ways = group.ways.iter();
self.relations = group.relations.iter();
None
}
None => Some(None),
},
ElementsIterState::DenseNode => match self.dense_nodes.next() {
Some(dense_node) => Some(Some(Element::DenseNode(dense_node))),
None => {
self.state = ElementsIterState::Node;
None
}
},
ElementsIterState::Node => match self.nodes.next() {
Some(node) => Some(Some(Element::Node(Node::new(self.block, node)))),
None => {
self.state = ElementsIterState::Way;
None
}
},
ElementsIterState::Way => match self.ways.next() {
Some(way) => Some(Some(Element::Way(Way::new(self.block, way)))),
None => {
self.state = ElementsIterState::Relation;
None
}
},
ElementsIterState::Relation => match self.relations.next() {
Some(rel) => Some(Some(Element::Relation(Relation::new(self.block, rel)))),
None => {
self.state = ElementsIterState::Group;
None
}
},
}
}
}
impl<'a> Iterator for BlockElementsIter<'a> {
type Item = Element<'a>;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
loop {
if let Some(element) = self.step() {
return element;
}
}
}
}
#[derive(Clone, Debug)]
pub struct GroupIter<'a> {
block: &'a osmformat::PrimitiveBlock,
groups: std::slice::Iter<'a, osmformat::PrimitiveGroup>,
}
impl<'a> GroupIter<'a> {
fn new(block: &'a osmformat::PrimitiveBlock) -> GroupIter<'a> {
GroupIter {
block,
groups: block.primitivegroup.iter(),
}
}
}
impl<'a> Iterator for GroupIter<'a> {
type Item = PrimitiveGroup<'a>;
fn next(&mut self) -> Option<Self::Item> {
match self.groups.next() {
Some(g) => Some(PrimitiveGroup::new(self.block, g)),
None => None,
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.groups.size_hint()
}
}
impl<'a> ExactSizeIterator for GroupIter<'a> {}
#[derive(Clone, Debug)]
pub struct GroupNodeIter<'a> {
block: &'a osmformat::PrimitiveBlock,
nodes: std::slice::Iter<'a, osmformat::Node>,
}
impl<'a> GroupNodeIter<'a> {
fn new(
block: &'a osmformat::PrimitiveBlock,
group: &'a osmformat::PrimitiveGroup,
) -> GroupNodeIter<'a> {
GroupNodeIter {
block,
nodes: group.nodes.iter(),
}
}
}
impl<'a> Iterator for GroupNodeIter<'a> {
type Item = Node<'a>;
fn next(&mut self) -> Option<Self::Item> {
match self.nodes.next() {
Some(n) => Some(Node::new(self.block, n)),
None => None,
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.nodes.size_hint()
}
}
impl<'a> ExactSizeIterator for GroupNodeIter<'a> {}
#[derive(Clone, Debug)]
pub struct GroupWayIter<'a> {
block: &'a osmformat::PrimitiveBlock,
ways: std::slice::Iter<'a, osmformat::Way>,
}
impl<'a> GroupWayIter<'a> {
fn new(
block: &'a osmformat::PrimitiveBlock,
group: &'a osmformat::PrimitiveGroup,
) -> GroupWayIter<'a> {
GroupWayIter {
block,
ways: group.ways.iter(),
}
}
}
impl<'a> Iterator for GroupWayIter<'a> {
type Item = Way<'a>;
fn next(&mut self) -> Option<Self::Item> {
match self.ways.next() {
Some(way) => Some(Way::new(self.block, way)),
None => None,
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.ways.size_hint()
}
}
impl<'a> ExactSizeIterator for GroupWayIter<'a> {}
#[derive(Clone, Debug)]
pub struct GroupRelationIter<'a> {
block: &'a osmformat::PrimitiveBlock,
rels: std::slice::Iter<'a, osmformat::Relation>,
}
impl<'a> GroupRelationIter<'a> {
fn new(
block: &'a osmformat::PrimitiveBlock,
group: &'a osmformat::PrimitiveGroup,
) -> GroupRelationIter<'a> {
GroupRelationIter {
block,
rels: group.relations.iter(),
}
}
}
impl<'a> Iterator for GroupRelationIter<'a> {
type Item = Relation<'a>;
fn next(&mut self) -> Option<Self::Item> {
match self.rels.next() {
Some(rel) => Some(Relation::new(self.block, rel)),
None => None,
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.rels.size_hint()
}
}
impl<'a> ExactSizeIterator for GroupRelationIter<'a> {}
pub(crate) fn str_from_stringtable(
block: &osmformat::PrimitiveBlock,
index: usize,
) -> Result<&str> {
if let Some(vec) = block.stringtable.s.get(index) {
std::str::from_utf8(vec)
.map_err(|e| new_error(ErrorKind::StringtableUtf8 { err: e, index }))
} else {
Err(new_error(ErrorKind::StringtableIndexOutOfBounds { index }))
}
}
pub(crate) fn get_stringtable_key_value(
block: &osmformat::PrimitiveBlock,
key_index: Option<usize>,
value_index: Option<usize>,
) -> Option<(&str, &str)> {
match (key_index, value_index) {
(Some(key_index), Some(val_index)) => {
let k_res = str_from_stringtable(block, key_index);
let v_res = str_from_stringtable(block, val_index);
if let (Ok(k), Ok(v)) = (k_res, v_res) {
Some((k, v))
} else {
None
}
}
_ => None,
}
}