pbf-reader 0.1.9

Fast openstreetmap PBF file format reader. Reads Nodes, Ways, Relations. It uses mpsc::channell and multiple threads to do job as fast as possible.
// Copyright (c) Oleksandr Omelchuk <kaznashcho()gmail.com>

pub type IDType = u32;
pub type LType = i64; // original latitude / longtitude
pub type CoordType = f64;

/// Coordinate tupple
#[derive(Debug, Clone, PartialEq, Eq)]
#[repr(C)]
pub struct Tup {
    /// Latitude
    pub lat: LType,
    /// Lontitude
    pub lon: LType,
}

/// Coordinate tupple
#[derive(Debug, Clone, PartialEq)]
#[repr(C)]
pub struct Coord {
    /// Latitude
    pub lat: CoordType,
    /// Lontitude
    pub lon: CoordType,
}

/// Node with assosiated tags http://wiki.openstreetmap.org/wiki/Node
#[derive(Debug, Clone, PartialEq)]
#[repr(C)]
pub struct Node {
    /// Node coordinate
    pub coord: Coord,
    /// List of tags
    pub tags: Tags,
}

/// Way http://wiki.openstreetmap.org/wiki/Way
#[derive(Debug, Clone, PartialEq, Eq)]
#[repr(C)]
pub struct Way {
    /// list of nodes ID
    pub nodes: Vec<IDType>,
    /// Way tags
    pub tags: Tags,
}

/// Type of object stored in Relation
#[derive(Debug, Clone, PartialEq, Eq)]
#[repr(C)]
pub enum RelationMemeberType {
    /// relation id is for Node type
    Node,
    /// relation id is for Way type
    Way,
    /// relation id is for Relation type
    Relation,
}

/// Relation item
#[derive(Debug, Clone, PartialEq, Eq)]
#[repr(C)]
pub struct RelationMemeber {
    /// ID of relation member
    pub member_id: IDType,
    /// Type of relation member
    pub member_type: RelationMemeberType,
    /// Index of string in parent_relation.tags.string_table_id
    pub role_id: IDType,
}

/// Relation of other osm objects
#[derive(Debug, Clone, PartialEq, Eq)]
#[repr(C)]
pub struct Relation {
    /// Telation tags
    pub tags: Tags,
    /// List of relation items
    pub members: Vec<RelationMemeber>,
}

/// Strings table contain strings used by Tags.
#[derive(Debug, Clone, PartialEq, Eq)]
#[repr(C)]
pub struct Strings {
    /// Strings container
    pub strings: Vec<String>,
}

/// Lightwait Tag representation which contains indices from it's parent Strings table.
#[derive(Debug, Clone, PartialEq, Eq)]
#[repr(C)]
pub struct Tag {
    /// key string index
    pub key: IDType,
    /// value string index
    pub val: IDType,
}

/// Tags
#[derive(Debug, Clone, PartialEq, Eq)]
#[repr(C)]
pub struct Tags {
    /// String table id used to match tags indexes.
    pub string_table_id: IDType,
    /// list of key-value tags.
    pub tags: Vec<Tag>,
}

impl Tags {
    /// Computes tags as a map of String:String
    pub fn get_keys_vals<'a>(&'a self, string_table: &'a Strings) -> Vec<(&'a String, &'a String)> {
        let mut kvls = Vec::with_capacity(self.tags.len());
        for tag in &self.tags {
            assert!(tag.key != 0);
            assert!(tag.val != 0);
            match string_table.strings.get(tag.key as usize) {
                Some(key) => match string_table.strings.get(tag.val as usize) {
                    Some(value) => {
                        kvls.push((key, value));
                    }
                    None => println!("WARNING: failed to map tags key."),
                },
                None => println!("WARNING: failed to map tags value."),
            }
        }
        kvls
    }
}

/// Bounding box
#[derive(Debug, Clone, PartialEq)]
#[repr(C)]
pub struct LBox {
    /// top left bound
    pub top_left: Coord,
    /// bottom right bound
    pub bottom_right: Coord,
}

#[macro_export]
macro_rules! pbf_min {
    ($x:expr, $y:expr) => ( if $x < $y { $x } else { $y } );
}
#[macro_export]
macro_rules! pbf_max {
    ($x:expr, $y:expr) => ( if $x > $y { $x } else { $y } );
}

impl LBox {
    pub fn union_with_box<'a>(mut self, other: &LBox) -> LBox {
        if self.top_left.lat > other.top_left.lat {
            self.top_left.lat = other.top_left.lat;
        }
        if self.top_left.lon > other.top_left.lon {
            self.top_left.lon = other.top_left.lon;
        }
        if self.bottom_right.lat < other.bottom_right.lat {
            self.bottom_right.lat = other.bottom_right.lat;
        }
        if self.bottom_right.lon < other.bottom_right.lon {
            self.bottom_right.lon = other.bottom_right.lon;
        }
        self
    }
    pub fn union_with_coord<'a>(&'a mut self, other: &Coord) {
        if self.top_left.lat > other.lat {
            self.top_left.lat = other.lat;
        }
        if self.top_left.lon > other.lon {
            self.top_left.lon = other.lon;
        }
        if self.bottom_right.lat < other.lat {
            self.bottom_right.lat = other.lat;
        }
        if self.bottom_right.lon < other.lon {
            self.bottom_right.lon = other.lon;
        }
    }
}

/// Coordinates of data in
#[derive(Debug, Clone, PartialEq, Eq)]
#[repr(C)]
pub struct BlobPosition {
    /// strat byte in flile
    pub start: usize,
    /// blob size
    pub size: usize,
}

/// General file info
#[derive(Debug, Clone, PartialEq)]
#[repr(C)]
pub struct PbfInfo {
    /// left right top bottom coordinate in nanodegrees
    pub bbox: LBox,
    /// osm blob position
    pub position: BlobPosition,
}

/// Generalized type used to transfer entities.
/// Using vectors for transfering relative set of entities
#[derive(Debug, Clone, PartialEq)]
pub enum PBFData {
    /// got set of Nodes
    NodesSet(Vec<(IDType, Node)>),
    /// got set of Ways
    WaysSet(Vec<(IDType, Way)>),
    /// got set of Relations
    RelationsSet(Vec<(IDType, Relation)>),
    /// got Strings table
    Strings(IDType, Strings),
    /// got PBF statisstics
    PbfInfo(PbfInfo),
    /// Parse job has finished. Time to join threads.
    ParseEnd,
}