ovtile/mapbox/
vector_layer.rs

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