Skip to content

Commit

Permalink
version 0.0.1
Browse files Browse the repository at this point in the history
  • Loading branch information
ciscorn committed Oct 29, 2024
1 parent 7b3b6be commit ad333a0
Show file tree
Hide file tree
Showing 8 changed files with 83 additions and 75 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
[package]
name = "tinymvt"
version = "0.1.0"
version = "0.0.1"
edition = "2021"
license = "MIT"
description = "Simple library for serializing Mapbox Vector Tile (MVT) with minimal dependencies."

[dependencies]
ahash = "0.8.11"
Expand Down
14 changes: 12 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,17 @@
# tinymvt
# tinymvt-rs

[![codecov](https://codecov.io/gh/MIERUNE/tinymvt/graph/badge.svg?token=HSPd9MRmxC)](https://codecov.io/gh/MIERUNE/tinymvt)
![Crates.io Version](https://img.shields.io/crates/v/tinymvt)

A simple Rust library for serializing Mapbox Vector Tile (MVT) with few dependencies.
A minimal Rust toolkit for serializing Mapbox Vector Tiles (MVT).

License: MIT

Includes the following utilities:

- Protobuf ([prost](https://github.com/tokio-rs/prost)) data types for MVT
- Geometry encoder
- Tags encoder
- Conversion between Web Mercator and geographic coordinates
- Conversion between linear tile IDs (PMTiles-compliant Hilbert id) and XYZ tile IDs

24 changes: 13 additions & 11 deletions examples/demo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ use std::fs;
use prost::Message;
use tinymvt::geometry::GeometryEncoder;
use tinymvt::tag::{TagsEncoder, Value};
use tinymvt::vector_tile::tile::{Feature, GeomType, Layer};
use tinymvt::vector_tile::Tile;
use tinymvt::vector_tile::{
tile::{Feature, GeomType, Layer},
Tile,
};

fn main() {
let extent = 4096;
Expand All @@ -25,12 +27,12 @@ fn main() {
[extent - 900, 900],
]);

tags_enc.add("foo", 10.into());
tags_enc.add("bar", 20.5.into());
tags_enc.add("foo", 10);
tags_enc.add("bar", 20.5);

Feature {
id: Some(1),
tags: tags_enc.flush_tags(),
tags: tags_enc.take_tags(),
r#type: Some(GeomType::Point as i32),
geometry: geom_enc.into_vec(),
}
Expand All @@ -56,13 +58,13 @@ fn main() {
tags_enc.add("sint", Value::SInt(-10));
tags_enc.add("int", Value::Int(10));
tags_enc.add("string", Value::String("string".to_string()));
tags_enc.add("float", 10.5f32.into());
tags_enc.add("double", 10.5f64.into());
tags_enc.add("float", 10.5f32);
tags_enc.add("double", 10.5f64);
tags_enc.add("bool", Value::Bool(true));

Feature {
id: Some(2),
tags: tags_enc.flush_tags(),
tags: tags_enc.take_tags(),
r#type: Some(GeomType::Linestring as i32),
geometry: geom_enc.into_vec(),
}
Expand All @@ -79,12 +81,12 @@ fn main() {
geom_enc.add_ring([[2200, 2200], [2300, 2200], [2300, 2300], [2200, 2300]]);
geom_enc.add_ring([[2300, 2300], [2400, 2300], [2400, 2400], [2300, 2400]]);

tags_enc.add("fizz", 10.into());
tags_enc.add("buzz", 20.5.into());
tags_enc.add("fizz", 10);
tags_enc.add("buzz", 20.5);

Feature {
id: Some(3),
tags: tags_enc.flush_tags(),
tags: tags_enc.take_tags(),
r#type: Some(GeomType::Polygon as i32),
geometry: geom_enc.into_vec(),
}
Expand Down
5 changes: 3 additions & 2 deletions src/geometry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,24 @@ const GEOM_COMMAND_CLOSE_PATH: u32 = 7;
const GEOM_COMMAND_MOVE_TO_WITH_COUNT1: u32 = 1 << 3 | GEOM_COMMAND_MOVE_TO;
const GEOM_COMMAND_CLOSE_PATH_WITH_COUNT1: u32 = 1 << 3 | GEOM_COMMAND_CLOSE_PATH;

/// Utility for encoding MVT geometries.
pub struct GeometryEncoder {
buf: Vec<u32>,
prev_x: i16,
prev_y: i16,
}

/// Utility for encoding MVT geometries.
impl GeometryEncoder {
// TODO: with_capacity
pub fn new() -> Self {
// TODO: with_capacity?
Self {
buf: Vec::new(),
prev_x: 0,
prev_y: 0,
}
}

/// Consumes the encoder and returns the encoded geometry.
#[inline]
pub fn into_vec(self) -> Vec<u32> {
self.buf
Expand Down
73 changes: 37 additions & 36 deletions src/tag.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
//! Tag (attribute) encoder for MVT.
use ahash::RandomState;
use indexmap::IndexSet;

Expand All @@ -18,8 +16,14 @@ impl TagsEncoder {
Default::default()
}

/// Adds a key-value pair for the current feature.
#[inline]
pub fn add(&mut self, key: &str, value: impl Into<Value>) {
self.add_inner(key, value.into());
}

#[inline]
pub fn add(&mut self, key: &str, value: Value) {
fn add_inner(&mut self, key: &str, value: Value) {
let key_idx = match self.keys.get_index_of(key) {
None => self.keys.insert_full(key.to_string()).0,
Some(idx) => idx,
Expand All @@ -31,11 +35,13 @@ impl TagsEncoder {
self.tags.extend([key_idx as u32, value_idx as u32]);
}

/// Takes the key-value index buffer for the current feature.
#[inline]
pub fn flush_tags(&mut self) -> Vec<u32> {
pub fn take_tags(&mut self) -> Vec<u32> {
std::mem::take(&mut self.tags)
}

/// Consumes the encoder and returns the keys and values for a layer.
#[inline]
pub fn into_keys_and_values(self) -> (Vec<String>, Vec<tile::Value>) {
let keys = self.keys.into_iter().collect();
Expand All @@ -48,12 +54,7 @@ impl TagsEncoder {
}
}

pub struct KeysAndValues {
pub keys: Vec<String>,
pub values: Vec<tile::Value>,
}

/// Wrapper for MVT values
/// Comperative wrapper for the MVT values.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum Value {
String(String),
Expand Down Expand Up @@ -162,34 +163,34 @@ mod test {
#[test]
fn tags_encoder() {
let mut encoder = TagsEncoder::new();
encoder.add("k0", "v0".into());
encoder.add("k0", "v0".into());
encoder.add("k1", "v0".into());
encoder.add("k1", "v1".into());
assert_eq!(encoder.flush_tags(), [0, 0, 0, 0, 1, 0, 1, 1]);

encoder.add("k0", "v0".into());
encoder.add("k0", "v2".into());
encoder.add("k1", "v2".into());
encoder.add("k2", "v0".to_string().into());
encoder.add("k1", "v1".into());
encoder.add("k1", "v1".to_string().into());
assert_eq!(encoder.flush_tags(), [0, 0, 0, 2, 1, 2, 2, 0, 1, 1, 1, 1]);

encoder.add("k1", 10i32.into());
encoder.add("k2", 10.5f64.into());
encoder.add("k3", 10u32.into());
encoder.add("k3", (-10i32).into());
encoder.add("k3", true.into());
encoder.add("k3", 1.into());
encoder.add("k2", 10.5f32.into());
encoder.add("k4", 10.5f64.into());
encoder.add("k3", (-10i64).into());
encoder.add("k3", 10u64.into());
encoder.add("k0", "v0");
encoder.add("k0", "v0");
encoder.add("k1", "v0");
encoder.add("k1", "v1");
assert_eq!(encoder.take_tags(), [0, 0, 0, 0, 1, 0, 1, 1]);

encoder.add("k0", "v0");
encoder.add("k0", "v2");
encoder.add("k1", "v2");
encoder.add("k2", "v0".to_string());
encoder.add("k1", "v1");
encoder.add("k1", "v1".to_string());
assert_eq!(encoder.take_tags(), [0, 0, 0, 2, 1, 2, 2, 0, 1, 1, 1, 1]);

encoder.add("k1", 10i32);
encoder.add("k2", 10.5f64);
encoder.add("k3", 10u32);
encoder.add("k3", -10i32);
encoder.add("k3", true);
encoder.add("k3", 1);
encoder.add("k2", 10.5f32);
encoder.add("k4", 10.5f64);
encoder.add("k3", -10i64);
encoder.add("k3", 10u64);
encoder.add("k5", Value::Int(11));
encoder.add("k5", 12i64.into());
encoder.add("k5", 12i64);
assert_eq!(
encoder.flush_tags(),
encoder.take_tags(),
[1, 3, 2, 4, 3, 3, 3, 5, 3, 6, 3, 7, 2, 8, 4, 4, 3, 5, 3, 3, 5, 9, 5, 10]
);

Expand Down
12 changes: 1 addition & 11 deletions src/vector_tile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,17 +72,7 @@ pub mod tile {
pub extent: ::core::option::Option<u32>,
}
/// GeomType is described in section 4.3.4 of the specification
#[derive(
Clone,
Copy,
Debug,
PartialEq,
Eq,
Hash,
PartialOrd,
Ord,
::prost::Enumeration
)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
#[repr(i32)]
pub enum GeomType {
Unknown = 0,
Expand Down
24 changes: 13 additions & 11 deletions tests/make_tile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ use std::fs;
use prost::Message;
use tinymvt::geometry::GeometryEncoder;
use tinymvt::tag::{TagsEncoder, Value};
use tinymvt::vector_tile::tile::{Feature, GeomType, Layer};
use tinymvt::vector_tile::Tile;
use tinymvt::vector_tile::{
tile::{Feature, GeomType, Layer},
Tile,
};

#[test]
fn make_tile() {
Expand All @@ -27,12 +29,12 @@ fn make_tile() {
[extent - 900, 900],
]);

tags_enc.add("foo", 10.into());
tags_enc.add("bar", 20.5.into());
tags_enc.add("foo", 10);
tags_enc.add("bar", 20.5);

Feature {
id: Some(1),
tags: tags_enc.flush_tags(),
tags: tags_enc.take_tags(),
r#type: Some(GeomType::Point as i32),
geometry: geom_enc.into_vec(),
}
Expand All @@ -59,13 +61,13 @@ fn make_tile() {
tags_enc.add("sint", Value::SInt(-10));
tags_enc.add("int", Value::Int(10));
tags_enc.add("string", Value::String("string".to_string()));
tags_enc.add("float", 10.5f32.into());
tags_enc.add("double", 10.5f64.into());
tags_enc.add("float", 10.5f32);
tags_enc.add("double", 10.5f64);
tags_enc.add("bool", Value::Bool(true));

Feature {
id: Some(2),
tags: tags_enc.flush_tags(),
tags: tags_enc.take_tags(),
r#type: Some(GeomType::Linestring as i32),
geometry: geom_enc.into_vec(),
}
Expand All @@ -84,12 +86,12 @@ fn make_tile() {
geom_enc.add_ring([[2200, 2200], [2300, 2200], [2300, 2300], [2200, 2300]]);
geom_enc.add_ring([[2300, 2300], [2400, 2300], [2400, 2400], [2300, 2400]]);

tags_enc.add("fizz", 10.into());
tags_enc.add("buzz", 20.5.into());
tags_enc.add("fizz", 10);
tags_enc.add("buzz", 20.5);

Feature {
id: Some(3),
tags: tags_enc.flush_tags(),
tags: tags_enc.take_tags(),
r#type: Some(GeomType::Polygon as i32),
geometry: geom_enc.into_vec(),
}
Expand Down

0 comments on commit ad333a0

Please sign in to comment.