• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Open-S2 / open-vector-tile / #27

06 Dec 2024 02:32PM UTC coverage: 98.708% (+1.3%) from 97.451%
#27

push

Mr Martian
fix coveralls

8783 of 8898 relevant lines covered (98.71%)

58.5 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

99.1
/rust/vector_tile.rs
1
use pbf::{ProtoRead, Protobuf};
2

3
use alloc::collections::BTreeMap;
4
use alloc::rc::Rc;
5
use alloc::string::String;
6
use alloc::vec::Vec;
7

8
use core::cell::RefCell;
9

10
use crate::{
11
    base::BaseVectorTile,
12
    mapbox::MapboxVectorLayer,
13
    open::{
14
        write_layer, ColumnCacheReader, ColumnCacheWriter, ElevationData, FeatureType, ImageData,
15
        OpenVectorLayer, Properties,
16
    },
17
    VectorGeometry, VectorLines3DWithOffset, VectorLinesWithOffset, VectorPoints, VectorPoints3D,
18
    BBOX,
19
};
20

21
/// Methods that all vector features should have
22
pub trait VectorFeatureMethods {
23
    /// the id of the feature
24
    fn id(&self) -> Option<u64>;
25
    /// the version of the vector tile
26
    fn version(&self) -> u16;
27
    /// the properties
28
    fn properties(&self) -> Properties;
29
    /// the extent
30
    fn extent(&self) -> usize;
31
    /// the feature type
32
    fn get_type(&self) -> FeatureType;
33
    /// the bounding box
34
    fn bbox(&self) -> Option<BBOX>;
35
    /// whether the feature has m values
36
    fn has_m_values(&self) -> bool;
37
    /// whether the feature is a points type
38
    fn is_points(&self) -> bool;
39
    /// whether the feature is a line type
40
    fn is_lines(&self) -> bool;
41
    /// whether the feature is a polygon type
42
    fn is_polygons(&self) -> bool;
43
    /// whether the feature is a points 3D type
44
    fn is_points_3d(&self) -> bool;
45
    /// whether the feature is a line 3D type
46
    fn is_lines_3d(&self) -> bool;
47
    /// whether the feature is a polygon 3D type
48
    fn is_polygons_3d(&self) -> bool;
49
    /// regardless of the type, we return a flattend point array
50
    fn load_points(&mut self) -> VectorPoints;
51
    /// regardless of the type, we return a flattend point3D array
52
    fn load_points_3d(&mut self) -> VectorPoints3D;
53
    /// an array of lines. The offsets will be set to 0
54
    fn load_lines(&mut self) -> VectorLinesWithOffset;
55
    /// an array of 3D lines. The offsets will be set to 0
56
    fn load_lines_3d(&mut self) -> VectorLines3DWithOffset;
57
    /// (flattened geometry & tesslation if applicable, indices)
58
    fn load_geometry_flat(&mut self) -> (Vec<f64>, Vec<u32>);
59
    /// load the geometry
60
    fn load_geometry(&mut self) -> VectorGeometry;
61
    /// load the indices
62
    fn read_indices(&mut self) -> Vec<u32>;
63
    /// Add tesselation data to the geometry
64
    fn add_tesselation(&mut self, geometry: &mut Vec<f64>, multiplier: f64);
65
    /// Add 3D tesselation data to the geometry
66
    fn add_tesselation_3d(&mut self, geometry: &mut Vec<f64>, multiplier: f64);
67
}
68

69
/// Methods that all vector layers should have
70
pub trait VectorLayerMethods {
71
    /// the version of the vector tile layer.
72
    fn version(&self) -> u16;
73
    /// the name of the layer
74
    fn name(&self) -> String;
75
    /// the extent of the vector tile (only **512**, **1_024**, **2_048**, **4_096**, and **8_192**
76
    /// are supported for the open spec)
77
    fn extent(&self) -> usize;
78
    /// grab a feature from the layer
79
    fn feature(&mut self, i: usize) -> Option<&mut dyn VectorFeatureMethods>;
80
    /// length (layer count)
81
    fn len(&self) -> usize;
82
    /// empty (layer count is 0)
83
    fn is_empty(&self) -> bool;
84
}
85

86
/// Layer container supporting both mapbox and open vector layers
87
#[derive(Debug)]
88
pub enum VectorLayer {
89
    /// Mapbox vector layer
90
    Mapbox(MapboxVectorLayer),
91
    /// Open vector layer
92
    Open(OpenVectorLayer),
93
}
94
impl VectorLayerMethods for VectorLayer {
95
    fn version(&self) -> u16 {
24✔
96
        match self {
24✔
97
            VectorLayer::Mapbox(layer) => layer.version(),
6✔
98
            VectorLayer::Open(layer) => layer.version(),
18✔
99
        }
100
    }
24✔
101

102
    fn name(&self) -> String {
24✔
103
        match self {
24✔
104
            VectorLayer::Mapbox(layer) => layer.name(),
6✔
105
            VectorLayer::Open(layer) => layer.name(),
18✔
106
        }
107
    }
24✔
108

109
    fn extent(&self) -> usize {
24✔
110
        match self {
24✔
111
            VectorLayer::Mapbox(layer) => layer.extent(),
6✔
112
            VectorLayer::Open(layer) => layer.extent(),
18✔
113
        }
114
    }
24✔
115

116
    fn feature(&mut self, i: usize) -> Option<&mut dyn VectorFeatureMethods> {
45✔
117
        match self {
45✔
118
            VectorLayer::Mapbox(layer) => layer.feature(i),
9✔
119
            VectorLayer::Open(layer) => layer.feature(i),
36✔
120
        }
121
    }
45✔
122

123
    fn len(&self) -> usize {
27✔
124
        match self {
27✔
125
            VectorLayer::Mapbox(layer) => layer.len(),
9✔
126
            VectorLayer::Open(layer) => layer.len(),
18✔
127
        }
128
    }
27✔
129

130
    fn is_empty(&self) -> bool {
6✔
131
        match self {
6✔
132
            VectorLayer::Mapbox(layer) => layer.is_empty(),
3✔
133
            VectorLayer::Open(layer) => layer.is_empty(),
3✔
134
        }
135
    }
6✔
136
}
137

138
/// The vector tile struct that covers both "open" and "mapbox" specifications
139
#[derive(Debug)]
140
pub struct VectorTile {
141
    /// the layers in the vector tile
142
    pub layers: BTreeMap<String, VectorLayer>,
143
    /// indexes to track the layers. Needed for the open spec because we need the cache before we can
144
    /// parse layers and features
145
    layer_indexes: Vec<usize>,
146
    /// the protobuf for the vector tile
147
    pbf: Rc<RefCell<Protobuf>>,
148
    /// the column cache
149
    columns: Option<Rc<RefCell<ColumnCacheReader>>>,
150
    /// Elevation data
151
    pub elevation: Option<ElevationData>,
152
    /// Image data
153
    pub image: Option<ImageData>,
154
}
155
impl VectorTile {
156
    /// Create a new vector tile
157
    pub fn new(data: Vec<u8>, end: Option<usize>) -> Self {
24✔
158
        let pbf = Rc::new(RefCell::new(data.into()));
24✔
159
        let mut vt = VectorTile {
24✔
160
            pbf: pbf.clone(),
24✔
161
            columns: None,
24✔
162
            layer_indexes: Vec::new(),
24✔
163
            layers: BTreeMap::new(),
24✔
164
            elevation: None,
24✔
165
            image: None,
24✔
166
        };
24✔
167

24✔
168
        pbf.borrow_mut().read_fields(&mut vt, end);
24✔
169

24✔
170
        if !vt.layer_indexes.is_empty() {
24✔
171
            vt.read_layers();
9✔
172
        }
15✔
173

174
        vt
24✔
175
    }
24✔
176

177
    /// Read the layers
178
    pub fn read_layers(&mut self) -> Option<()> {
9✔
179
        let layer_indexes = self.layer_indexes.clone();
9✔
180
        let mut tmp_pbf = self.pbf.borrow_mut();
9✔
181
        let cache = self.columns.as_ref()?.clone();
9✔
182

183
        for pos in layer_indexes {
30✔
184
            tmp_pbf.set_pos(pos);
21✔
185
            let mut layer = OpenVectorLayer::new(cache.clone());
21✔
186
            tmp_pbf.read_message(&mut layer);
21✔
187
            self.layers.insert(layer.name.clone(), VectorLayer::Open(layer));
21✔
188
        }
21✔
189

190
        Some(())
9✔
191
    }
9✔
192

193
    /// Get a layer given the name
194
    pub fn layer(&mut self, name: &str) -> Option<&mut VectorLayer> {
27✔
195
        self.layers.get_mut(name)
27✔
196
    }
27✔
197
}
198
impl ProtoRead for VectorTile {
199
    fn read(&mut self, tag: u64, pb: &mut Protobuf) {
48✔
200
        match tag {
48✔
201
            1 | 3 => {
9✔
202
                let mut layer = MapboxVectorLayer::new(self.pbf.clone(), tag == 1);
9✔
203
                pb.read_message(&mut layer);
9✔
204
                self.layers.insert(layer.name.clone(), VectorLayer::Mapbox(layer));
9✔
205
            }
9✔
206
            4 => {
21✔
207
                // store the position of each layer for later retrieval.
21✔
208
                // Columns must be prepped before reading the layer.
21✔
209
                self.layer_indexes.push(pb.get_pos());
21✔
210
            }
21✔
211
            5 => {
12✔
212
                let mut column_reader = ColumnCacheReader::new();
12✔
213
                pb.read_message(&mut column_reader);
12✔
214
                self.columns = Some(Rc::new(RefCell::new(column_reader)));
12✔
215
            }
12✔
216
            6 => {
3✔
217
                let mut elevation = ElevationData::default();
3✔
218
                pb.read_message(&mut elevation);
3✔
219
                self.elevation = Some(elevation);
3✔
220
            }
3✔
221
            7 => {
3✔
222
                let mut image = ImageData::default();
3✔
223
                pb.read_message(&mut image);
3✔
224
                self.image = Some(image);
3✔
225
            }
3✔
226
            #[tarpaulin::skip]
227
            _ => panic!("unknown tag: {}", tag),
×
228
        }
229
    }
48✔
230
}
231

232
/// writer for converting a BaseVectorTile to encoded bytes of the Open Vector Tile format
233
pub fn write_tile(tile: &mut BaseVectorTile, image: Option<&ImageData>) -> Vec<u8> {
12✔
234
    let mut pbf = Protobuf::new();
12✔
235
    let mut cache = ColumnCacheWriter::default();
12✔
236

237
    // first write layers
238
    for layer in tile.layers.values_mut() {
21✔
239
        pbf.write_bytes_field(4, &write_layer(layer, &mut cache));
21✔
240
    }
21✔
241
    // now we can write columns
242
    pbf.write_message(5, &cache);
12✔
243
    // if an image exists, let's write it
244
    if let Some(image) = image {
12✔
245
        pbf.write_message(7, image);
3✔
246
    }
9✔
247

248
    pbf.take()
12✔
249
}
12✔
250

251
/// write elevation tile
252
pub fn write_elevation_tile(e_data: &mut ElevationData) -> Vec<u8> {
3✔
253
    let mut pbf = Protobuf::new();
3✔
254

3✔
255
    pbf.write_message(6, e_data);
3✔
256

3✔
257
    pbf.take()
3✔
258
}
3✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc