use crate::{
VectorFeature,
base::BaseVectorTile,
mapbox::MapboxVectorLayer,
open::{
ColumnCacheReader, ColumnCacheWriter, GridData, ImageData, OpenVectorLayer, write_layer,
},
};
use alloc::{collections::BTreeMap, rc::Rc, string::String, vec::Vec};
use core::cell::RefCell;
use pbf::{ProtoRead, Protobuf};
pub trait VectorLayerMethods {
fn version(&self) -> u16;
fn name(&self) -> String;
fn extent(&self) -> usize;
fn feature(&mut self, i: usize) -> Option<VectorFeature<'_>>;
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<VectorFeature<'_>> {
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);
}
_ => 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(grids) = grids {
for grid in grids.iter() {
pbf.write_message(6, *grid);
}
}
if let Some(images) = images {
for image in images.iter() {
pbf.write_message(7, *image);
}
}
pbf.take()
}