open_vector_tile/mapbox/
vector_layer.rs

1use crate::{
2    VectorFeatureMethods, VectorLayerMethods,
3    base::BaseVectorLayer,
4    mapbox::{MapboxVectorFeature, write_feature},
5};
6use alloc::{
7    collections::{BTreeMap, btree_map::Entry},
8    rc::Rc,
9    string::String,
10    vec::Vec,
11};
12use core::cell::RefCell;
13use pbf::{ProtoRead, Protobuf};
14use s2json::PrimitiveValue;
15
16/// Mapbox specification for a Layer
17#[derive(Debug)]
18pub struct MapboxVectorLayer {
19    /// the version of the vector tile layer.
20    pub version: u16,
21    /// the name of the layer
22    pub name: String,
23    /// the extent of the vector layer
24    pub extent: usize,
25    /// the features in the layer
26    pub features: BTreeMap<usize, MapboxVectorFeature>,
27    /// track the positions of the features
28    pub feature_positions: Vec<usize>,
29    /// whether or not the layer is an s2 layer. This is an extension to the Mapbox spec and not used
30    /// in production by most tools
31    is_s2: bool,
32    /// a reference to the pbf
33    pbf: Rc<RefCell<Protobuf>>,
34    /// key store used by features
35    keys: Rc<RefCell<Vec<String>>>,
36    /// value store used by features
37    values: Rc<RefCell<Vec<PrimitiveValue>>>,
38}
39impl MapboxVectorLayer {
40    /// Create a new MapboxVectorLayer
41    pub fn new(pbf: Rc<RefCell<Protobuf>>, is_s2: bool) -> MapboxVectorLayer {
42        MapboxVectorLayer {
43            version: 5,
44            name: String::new(),
45            extent: 4_096,
46            is_s2,
47            pbf: pbf.clone(),
48            keys: Rc::new(RefCell::new(Vec::new())),
49            values: Rc::new(RefCell::new(Vec::new())),
50            features: BTreeMap::new(),
51            feature_positions: Vec::new(),
52        }
53    }
54}
55impl VectorLayerMethods for MapboxVectorLayer {
56    fn version(&self) -> u16 {
57        self.version
58    }
59
60    fn name(&self) -> String {
61        self.name.clone()
62    }
63
64    fn extent(&self) -> usize {
65        self.extent
66    }
67
68    /// the number of features in the layer
69    fn len(&self) -> usize {
70        self.feature_positions.len()
71    }
72
73    /// Check if the layer is empty
74    fn is_empty(&self) -> bool {
75        self.feature_positions.is_empty()
76    }
77
78    fn feature(&mut self, i: usize) -> Option<&mut dyn VectorFeatureMethods> {
79        // First check if self.features already has the feature
80        if let Entry::Vacant(e) = self.features.entry(i) {
81            // Read the feature
82            let mut feature = MapboxVectorFeature::new(
83                self.pbf.clone(),
84                self.is_s2,
85                self.extent,
86                self.version,
87                self.keys.clone(),
88                self.values.clone(),
89            );
90            let mut pbf = self.pbf.borrow_mut();
91            pbf.set_pos(self.feature_positions[i]);
92            pbf.read_message(&mut feature);
93            e.insert(feature);
94
95            // Now safely retrieve the inserted feature
96            Some(self.features.get_mut(&i).unwrap() as &mut dyn VectorFeatureMethods)
97        } else {
98            // Safe to unwrap since we just checked the key exists
99            Some(self.features.get_mut(&i).unwrap() as &mut dyn VectorFeatureMethods)
100        }
101    }
102}
103impl ProtoRead for MapboxVectorLayer {
104    fn read(&mut self, tag: u64, pb: &mut Protobuf) {
105        match tag {
106            15 => self.version = pb.read_varint::<u16>(),
107            1 => self.name = pb.read_string(),
108            2 => self.feature_positions.push(pb.get_pos()),
109            3 => {
110                self.keys.borrow_mut().push(pb.read_string());
111            }
112            4 => {
113                let mut value = PrimitiveValue::Null;
114                pb.read_message(&mut value);
115                self.values.borrow_mut().push(value);
116            }
117            5 => self.extent = pb.read_varint::<usize>(),
118            _ => panic!("Unknown layer type"),
119        }
120    }
121}
122
123/// Write a layer to a protobuffer using the S2 Specification
124pub fn write_layer(layer: &BaseVectorLayer, mapbox_support: bool) -> Vec<u8> {
125    let mut pbf = Protobuf::new();
126    let mut keys: BTreeMap<String, usize> = BTreeMap::new();
127    let mut values: BTreeMap<PrimitiveValue, usize> = BTreeMap::new();
128
129    pbf.write_varint_field(15, if mapbox_support { 1 } else { 5 });
130    pbf.write_string_field(1, &layer.name);
131    for feature in layer.features.iter() {
132        pbf.write_bytes_field(2, &write_feature(feature, &mut keys, &mut values, mapbox_support));
133    }
134    let mut keys: Vec<(String, usize)> = keys.into_iter().collect();
135    keys.sort_by(|a, b| a.1.cmp(&b.1));
136    // keys and values
137    for (key, _) in keys.iter() {
138        pbf.write_string_field(3, key);
139    }
140    let mut values: Vec<(PrimitiveValue, usize)> = values.into_iter().collect();
141    values.sort_by(|a, b| a.1.cmp(&b.1));
142    for (value, _) in values.iter() {
143        pbf.write_message(4, value);
144    }
145    pbf.write_varint_field(5, layer.extent as usize);
146
147    pbf.take()
148}