tinymvt 0.3.0

A lightweight library for encoding and decoding Mapbox Vector Tiles (MVT)
Documentation
use std::env;
use std::fs;

use prost::Message;
use std::convert::TryFrom;
use tinymvt::geometry::GeometryDecoder;
use tinymvt::tag::TagsDecoder;
use tinymvt::vector_tile::{tile::GeomType, Tile};

fn main() {
    let args: Vec<String> = env::args().collect();
    if args.len() != 2 {
        eprintln!("Usage: {} <path-to-mvt-file>", args[0]);
        std::process::exit(1);
    }

    let path = &args[1];
    let data = fs::read(path).expect("Failed to read MVT file");

    let tile = Tile::decode(&data[..]).expect("Failed to decode MVT protobuf");

    println!("layers={}", tile.layers.len());

    for layer in tile.layers.iter() {
        println!("layer.name={}", layer.name);
        println!("layer.version={}", layer.version);
        println!("layer.extent={}", layer.extent.unwrap_or(4096));
        println!("layer.features={}", layer.features.len());
        println!("layer.keys={}", layer.keys.len());
        println!("layer.values={}", layer.values.len());

        let tags_decoder = TagsDecoder::new(&layer.keys, &layer.values);

        for feature in layer.features.iter() {
            if let Some(id) = feature.id {
                println!("feature.id={}", id);
            }

            let geom_type = feature.r#type.and_then(|t| GeomType::try_from(t).ok());
            println!("feature.type={:?}", geom_type.unwrap_or(GeomType::Unknown));

            if !feature.tags.is_empty() {
                match tags_decoder.decode(&feature.tags) {
                    Ok(tags) => {
                        for (key, value) in tags {
                            println!("feature.tag.{}={}", key, format_value(&value));
                        }
                    }
                    Err(e) => {
                        println!("feature.tags.error={}", e);
                    }
                }
            }

            if !feature.geometry.is_empty() {
                match geom_type {
                    Some(GeomType::Point) => {
                        let mut decoder = GeometryDecoder::new(&feature.geometry);
                        match decoder.decode_points() {
                            Ok(points) => {
                                for point in points.iter() {
                                    println!("feature.point={},{}", point[0], point[1]);
                                }
                            }
                            Err(e) => println!("feature.geometry.error={}", e),
                        }
                    }
                    Some(GeomType::Linestring) => {
                        let mut decoder = GeometryDecoder::new(&feature.geometry);
                        match decoder.decode_linestrings() {
                            Ok(linestrings) => {
                                for ls in linestrings.iter() {
                                    for vertex in ls.iter() {
                                        println!(
                                            "feature.linestring.vertex={},{}",
                                            vertex[0], vertex[1]
                                        );
                                    }
                                }
                            }
                            Err(e) => println!("feature.geometry.error={}", e),
                        }
                    }
                    Some(GeomType::Polygon) => {
                        let mut decoder = GeometryDecoder::new(&feature.geometry);
                        match decoder.decode_polygons() {
                            Ok(polygons) => {
                                for polygon in polygons.iter() {
                                    for (ring_idx, ring) in polygon.iter().enumerate() {
                                        let ring_type = if ring_idx == 0 {
                                            "exterior"
                                        } else {
                                            "interior"
                                        };
                                        for vertex in ring.iter() {
                                            println!(
                                                "feature.polygon.{}.vertex={},{}",
                                                ring_type, vertex[0], vertex[1]
                                            );
                                        }
                                    }
                                }
                            }
                            Err(e) => println!("feature.geometry.error={}", e),
                        }
                    }
                    _ => {
                        println!("feature.geometry.raw={}", feature.geometry.len());
                    }
                }
            }
        }
    }
}

fn format_value(value: &tinymvt::tag::Value) -> String {
    use tinymvt::tag::Value;
    match value {
        Value::String(s) => format!("\"{}\"", s),
        Value::Float(bytes) => format!("{}", f32::from_ne_bytes(*bytes)),
        Value::Double(bytes) => format!("{}", f64::from_ne_bytes(*bytes)),
        Value::Int(i) => format!("{}", i),
        Value::Uint(u) => format!("{}", u),
        Value::SInt(s) => format!("{}", s),
        Value::Bool(b) => format!("{}", b),
    }
}