use crate::encoder::{GeomData, GeomType};
use crate::error::{Error, Result};
use crate::vector_tile::Tile as VecTile;
use crate::vector_tile::tile::{
Feature as VtFeature, GeomType as VtGeomType, Layer as VtLayer, Value,
};
use prost::Message;
use std::io::Write;
pub struct Tile {
vec_tile: VecTile,
extent: u32,
}
pub struct Layer {
layer: VtLayer,
}
pub struct Feature {
feature: VtFeature,
layer: Layer,
num_keys: usize,
num_values: usize,
}
impl Tile {
pub fn new(extent: u32) -> Self {
let vec_tile = VecTile::default();
Tile { vec_tile, extent }
}
pub fn extent(&self) -> u32 {
self.extent
}
pub fn num_layers(&self) -> usize {
self.vec_tile.layers.len()
}
pub fn create_layer(&self, name: &str) -> Layer {
Layer::new(name, self.extent)
}
pub fn add_layer(&mut self, layer: Layer) -> Result<()> {
if layer.layer.extent != Some(self.extent) {
return Err(Error::WrongExtent());
}
if self
.vec_tile
.layers
.iter()
.any(|n| n.name == layer.layer.name)
{
Err(Error::DuplicateName())
} else {
self.vec_tile.layers.push(layer.layer);
Ok(())
}
}
pub fn write_to(&self, out: &mut dyn Write) -> Result<()> {
out.write_all(&self.vec_tile.encode_to_vec())?;
Ok(())
}
pub fn to_bytes(&self) -> Result<Vec<u8>> {
Ok(self.vec_tile.encode_to_vec())
}
pub fn compute_size(&self) -> usize {
self.vec_tile.encoded_len()
}
}
impl Default for Layer {
fn default() -> Self {
let layer = VtLayer::default();
Layer { layer }
}
}
impl Layer {
fn new(name: &str, extent: u32) -> Self {
let layer = VtLayer {
version: 2,
name: name.to_string(),
extent: Some(extent),
..Default::default()
};
Layer { layer }
}
pub fn name(&self) -> Option<&str> {
Some(&self.layer.name)
}
pub fn num_features(&self) -> usize {
self.layer.features.len()
}
pub fn into_feature(self, geom_data: GeomData) -> Feature {
let num_keys = self.layer.keys.len();
let num_values = self.layer.values.len();
let feature = VtFeature {
r#type: Some(match geom_data.geom_type() {
GeomType::Point => VtGeomType::Point as i32,
GeomType::Linestring => VtGeomType::Linestring as i32,
GeomType::Polygon => VtGeomType::Polygon as i32,
}),
geometry: geom_data.into_vec(),
..Default::default()
};
Feature {
feature,
layer: self,
num_keys,
num_values,
}
}
fn key_pos(&mut self, key: &str) -> usize {
self.layer
.keys
.iter()
.position(|k| *k == key)
.unwrap_or_else(|| {
self.layer.keys.push(key.to_string());
self.layer.keys.len() - 1
})
}
fn val_pos(&mut self, value: Value) -> usize {
self.layer
.values
.iter()
.position(|v| *v == value)
.unwrap_or_else(|| {
self.layer.values.push(value);
self.layer.values.len() - 1
})
}
}
impl Feature {
pub fn into_layer(mut self) -> Layer {
self.layer.layer.features.push(self.feature);
self.layer
}
pub fn layer(mut self) -> Layer {
self.layer.layer.keys.truncate(self.num_keys);
self.layer.layer.values.truncate(self.num_values);
self.layer
}
pub fn set_id(&mut self, id: u64) {
let layer = &self.layer.layer;
if layer.features.iter().any(|f| f.id == Some(id)) {
log::warn!(
"Duplicate feature ID ({id}) in layer {:?}",
&layer.name
);
}
self.feature.id = Some(id);
}
pub fn num_tags(&self) -> usize {
self.feature.tags.len()
}
pub fn add_tag_string(&mut self, key: &str, val: &str) {
let value = Value {
string_value: Some(val.to_string()),
..Default::default()
};
self.add_tag(key, value);
}
pub fn add_tag_double(&mut self, key: &str, val: f64) {
let value = Value {
double_value: Some(val),
..Default::default()
};
self.add_tag(key, value);
}
pub fn add_tag_float(&mut self, key: &str, val: f32) {
let value = Value {
float_value: Some(val),
..Default::default()
};
self.add_tag(key, value);
}
pub fn add_tag_int(&mut self, key: &str, val: i64) {
let value = Value {
int_value: Some(val),
..Default::default()
};
self.add_tag(key, value);
}
pub fn add_tag_uint(&mut self, key: &str, val: u64) {
let value = Value {
uint_value: Some(val),
..Default::default()
};
self.add_tag(key, value);
}
pub fn add_tag_sint(&mut self, key: &str, val: i64) {
let value = Value {
sint_value: Some(val),
..Default::default()
};
self.add_tag(key, value);
}
pub fn add_tag_bool(&mut self, key: &str, val: bool) {
let value = Value {
bool_value: Some(val),
..Default::default()
};
self.add_tag(key, value);
}
fn add_tag(&mut self, key: &str, value: Value) {
let kidx = self.layer.key_pos(key);
self.feature.tags.push(kidx as u32);
let vidx = self.layer.val_pos(value);
self.feature.tags.push(vidx as u32);
}
}