use pbf::{ProtoRead, Protobuf};
use alloc::{collections::BTreeMap, rc::Rc, string::String, vec::Vec};
use core::cell::RefCell;
use crate::{
base::BaseVectorTile,
mapbox::MapboxVectorLayer,
open::{
write_layer, ColumnCacheReader, ColumnCacheWriter, FeatureType, GridData, ImageData,
OpenVectorLayer, Properties,
},
VectorGeometry, VectorLines3DWithOffset, VectorLinesWithOffset, VectorPoints, VectorPoints3D,
BBOX,
};
pub trait VectorFeatureMethods {
fn id(&self) -> Option<u64>;
fn version(&self) -> u16;
fn properties(&self) -> Properties;
fn extent(&self) -> usize;
fn get_type(&self) -> FeatureType;
fn bbox(&self) -> Option<BBOX>;
fn has_m_values(&self) -> bool;
fn is_points(&self) -> bool;
fn is_lines(&self) -> bool;
fn is_polygons(&self) -> bool;
fn is_points_3d(&self) -> bool;
fn is_lines_3d(&self) -> bool;
fn is_polygons_3d(&self) -> bool;
fn load_points(&mut self) -> VectorPoints;
fn load_points_3d(&mut self) -> VectorPoints3D;
fn load_lines(&mut self) -> VectorLinesWithOffset;
fn load_lines_3d(&mut self) -> VectorLines3DWithOffset;
fn load_geometry_flat(&mut self) -> (Vec<f64>, Vec<u32>);
fn load_geometry(&mut self) -> VectorGeometry;
fn read_indices(&mut self) -> Vec<u32>;
fn add_tesselation(&mut self, geometry: &mut Vec<f64>, multiplier: f64);
fn add_tesselation_3d(&mut self, geometry: &mut Vec<f64>, multiplier: f64);
}
pub trait VectorLayerMethods {
fn version(&self) -> u16;
fn name(&self) -> String;
fn extent(&self) -> usize;
fn feature(&mut self, i: usize) -> Option<&mut dyn VectorFeatureMethods>;
fn len(&self) -> usize;
fn is_empty(&self) -> bool;
}
#[derive(Debug)]
pub enum VectorLayer {
Mapbox(MapboxVectorLayer),
Open(OpenVectorLayer),
}
impl VectorLayerMethods for VectorLayer {
fn version(&self) -> u16 {
match self {
VectorLayer::Mapbox(layer) => layer.version(),
VectorLayer::Open(layer) => layer.version(),
}
}
fn name(&self) -> String {
match self {
VectorLayer::Mapbox(layer) => layer.name(),
VectorLayer::Open(layer) => layer.name(),
}
}
fn extent(&self) -> usize {
match self {
VectorLayer::Mapbox(layer) => layer.extent(),
VectorLayer::Open(layer) => layer.extent(),
}
}
fn feature(&mut self, i: usize) -> Option<&mut dyn VectorFeatureMethods> {
match self {
VectorLayer::Mapbox(layer) => layer.feature(i),
VectorLayer::Open(layer) => layer.feature(i),
}
}
fn len(&self) -> usize {
match self {
VectorLayer::Mapbox(layer) => layer.len(),
VectorLayer::Open(layer) => layer.len(),
}
}
fn is_empty(&self) -> bool {
match self {
VectorLayer::Mapbox(layer) => layer.is_empty(),
VectorLayer::Open(layer) => layer.is_empty(),
}
}
}
#[derive(Debug)]
pub struct VectorTile {
pub layers: BTreeMap<String, VectorLayer>,
layer_indexes: Vec<usize>,
pbf: Rc<RefCell<Protobuf>>,
columns: Option<Rc<RefCell<ColumnCacheReader>>>,
pub grids: BTreeMap<String, GridData>,
pub images: BTreeMap<String, ImageData>,
}
impl VectorTile {
pub fn new(data: Vec<u8>, end: Option<usize>) -> Self {
let pbf = Rc::new(RefCell::new(data.into()));
let mut vt = VectorTile {
pbf: pbf.clone(),
columns: None,
layer_indexes: Vec::new(),
layers: BTreeMap::new(),
grids: BTreeMap::new(),
images: BTreeMap::new(),
};
pbf.borrow_mut().read_fields(&mut vt, end);
if !vt.layer_indexes.is_empty() {
vt.read_layers();
}
vt
}
pub fn read_layers(&mut self) -> Option<()> {
let layer_indexes = self.layer_indexes.clone();
let mut tmp_pbf = self.pbf.borrow_mut();
let cache = self.columns.as_ref()?.clone();
for pos in layer_indexes {
tmp_pbf.set_pos(pos);
let mut layer = OpenVectorLayer::new(cache.clone());
tmp_pbf.read_message(&mut layer);
self.layers.insert(layer.name.clone(), VectorLayer::Open(layer));
}
Some(())
}
pub fn layer(&mut self, name: &str) -> Option<&mut VectorLayer> {
self.layers.get_mut(name)
}
}
impl ProtoRead for VectorTile {
fn read(&mut self, tag: u64, pb: &mut Protobuf) {
match tag {
1 | 3 => {
let mut layer = MapboxVectorLayer::new(self.pbf.clone(), tag == 1);
pb.read_message(&mut layer);
self.layers.insert(layer.name.clone(), VectorLayer::Mapbox(layer));
}
4 => {
self.layer_indexes.push(pb.get_pos());
}
5 => {
let mut column_reader = ColumnCacheReader::new();
pb.read_message(&mut column_reader);
self.columns = Some(Rc::new(RefCell::new(column_reader)));
}
6 => {
let mut grid = GridData::default();
pb.read_message(&mut grid);
self.grids.insert(grid.name.clone(), grid);
}
7 => {
let mut image = ImageData::default();
pb.read_message(&mut image);
self.images.insert(image.name.clone(), image);
}
#[tarpaulin::skip]
_ => panic!("unknown tag: {}", tag),
}
}
}
pub fn write_tile(
tile: Option<&mut BaseVectorTile>,
images: Option<Vec<&ImageData>>,
grids: Option<Vec<&GridData>>,
) -> Vec<u8> {
let mut pbf = Protobuf::new();
let mut cache = ColumnCacheWriter::default();
if let Some(tile) = tile {
for layer in tile.layers.values_mut() {
pbf.write_bytes_field(4, &write_layer(layer, &mut cache));
}
pbf.write_message(5, &cache);
}
if let Some(images) = images {
for image in images.iter() {
pbf.write_message(7, *image);
}
}
if let Some(grids) = grids {
for grid in grids.iter() {
pbf.write_message(6, *grid);
}
}
pbf.take()
}