1pub mod error;
62pub mod feature;
63pub mod layer;
64
65mod vector_tile;
66
67use feature::{Feature, Value};
68use geo_types::{
69 Coord, Geometry, LineString, MultiLineString, MultiPoint, MultiPolygon, Point, Polygon,
70};
71use layer::Layer;
72use prost::{Message, bytes::Bytes};
73use vector_tile::{Tile, tile::GeomType};
74
75const DIMENSION: u32 = 2;
77
78pub struct Reader {
80 tile: Tile,
81}
82
83impl Reader {
84 pub fn new(data: Vec<u8>) -> Result<Self, error::ParserError> {
103 match Tile::decode(Bytes::from(data)) {
104 Ok(tile) => Ok(Self { tile }),
105 Err(error) => Err(error::ParserError::new(error::DecodeError::new(Box::new(
106 error,
107 )))),
108 }
109 }
110
111 pub fn get_layer_names(&self) -> Result<Vec<String>, error::ParserError> {
137 process_layers(&self.tile.layers, |layer, _| layer.name.clone())
138 }
139
140 pub fn get_layer_metadata(&self) -> Result<Vec<Layer>, error::ParserError> {
167 process_layers(&self.tile.layers, |layer, index| Layer {
168 layer_index: index,
169 version: layer.version,
170 name: layer.name.clone(),
171 feature_count: layer.features.len(),
172 extent: layer.extent.unwrap_or(4096),
173 })
174 }
175
176 pub fn get_features(&self, layer_index: usize) -> Result<Vec<Feature>, error::ParserError> {
206 let layer = self.tile.layers.get(layer_index);
207 match layer {
208 Some(layer) => {
209 let mut features = Vec::with_capacity(layer.features.len());
210 for feature in layer.features.iter() {
211 if let Some(geom_type) = feature.r#type {
212 match GeomType::try_from(geom_type) {
213 Ok(geom_type) => {
214 let parsed_geometry = match parse_geometry(&feature.geometry, geom_type) {
215 Ok(parsed_geometry) => parsed_geometry,
216 Err(error) => {
217 return Err(error);
218 }
219 };
220
221 let parsed_tags = match parse_tags(&feature.tags, &layer.keys, &layer.values) {
222 Ok(parsed_tags) => parsed_tags,
223 Err(error) => {
224 return Err(error);
225 }
226 };
227
228 features.push(Feature {
229 geometry: parsed_geometry,
230 id: feature.id,
231 properties: Some(parsed_tags),
232 });
233 }
234 Err(error) => {
235 return Err(error::ParserError::new(error::DecodeError::new(Box::new(
236 error,
237 ))));
238 }
239 }
240 }
241 }
242 Ok(features)
243 }
244 None => Ok(vec![]),
245 }
246 }
247}
248
249fn process_layers<T, F>(
250 layers: &[vector_tile::tile::Layer],
251 mut processor: F,
252) -> Result<Vec<T>, error::ParserError>
253where
254 F: FnMut(&vector_tile::tile::Layer, usize) -> T,
255{
256 let mut results = Vec::with_capacity(layers.len());
257 for (index, layer) in layers.iter().enumerate() {
258 match layer.version {
259 1 | 2 => results.push(processor(layer, index)),
260 _ => {
261 return Err(error::ParserError::new(error::VersionError::new(
262 layer.name.clone(),
263 layer.version,
264 )));
265 }
266 }
267 }
268 Ok(results)
269}
270
271fn parse_tags(
272 tags: &[u32],
273 keys: &[String],
274 values: &[vector_tile::tile::Value],
275) -> Result<std::collections::HashMap<String, Value>, error::ParserError> {
276 let mut result = std::collections::HashMap::new();
277 for item in tags.chunks(2) {
278 if item.len() != 2
279 || item[0] >= keys.len().try_into().unwrap()
280 || item[1] >= values.len().try_into().unwrap()
281 {
282 return Err(error::ParserError::new(error::TagsError::new()));
283 }
284 result.insert(
285 keys[item[0] as usize].clone(),
286 map_value(values[item[1] as usize].clone()),
287 );
288 }
289 Ok(result)
290}
291
292fn map_value(value: vector_tile::tile::Value) -> Value {
293 if let Some(s) = value.string_value {
294 return Value::String(s);
295 }
296 if let Some(f) = value.float_value {
297 return Value::Float(f);
298 }
299 if let Some(d) = value.double_value {
300 return Value::Double(d);
301 }
302 if let Some(i) = value.int_value {
303 return Value::Int(i);
304 }
305 if let Some(u) = value.uint_value {
306 return Value::UInt(u);
307 }
308 if let Some(s) = value.sint_value {
309 return Value::SInt(s);
310 }
311 if let Some(b) = value.bool_value {
312 return Value::Bool(b);
313 }
314 Value::Null
315}
316
317fn shoelace_formula(points: &[Point<f32>]) -> f32 {
318 let mut area: f32 = 0.0;
319 let n = points.len();
320 let mut v1 = points[n - 1];
321 for v2 in points.iter().take(n) {
322 area += (v2.y() - v1.y()) * (v2.x() + v1.x());
323 v1 = *v2;
324 }
325 area * 0.5
326}
327
328fn parse_geometry(
329 geometry_data: &[u32],
330 geom_type: GeomType,
331) -> Result<Geometry<f32>, error::ParserError> {
332 if geom_type == GeomType::Unknown {
333 return Err(error::ParserError::new(error::GeometryError::new()));
334 }
335
336 let mut coordinates: Vec<Coord<f32>> = Vec::with_capacity(geometry_data.len());
338 let mut polygons: Vec<Polygon<f32>> = Vec::new();
339 let mut linestrings: Vec<LineString<f32>> = Vec::new();
340
341 let mut cursor: [i32; 2] = [0, 0];
342 let mut parameter_count: u32 = 0;
343
344 for value in geometry_data.iter() {
345 if parameter_count == 0 {
346 let command_integer = value;
347 let id = (command_integer & 0x7) as u8;
348 match id {
349 1 => {
350 parameter_count = (command_integer >> 3) * DIMENSION;
352 if geom_type == GeomType::Linestring && !coordinates.is_empty() {
353 linestrings.push(LineString::new(coordinates));
354 coordinates = Vec::with_capacity(geometry_data.len());
356 }
357 }
358 2 => {
359 parameter_count = (command_integer >> 3) * DIMENSION;
361 }
362 7 => {
363 let first_coordinate = match coordinates.first() {
365 Some(coord) => coord.to_owned(),
366 None => {
367 return Err(error::ParserError::new(error::GeometryError::new()));
368 }
369 };
370 coordinates.push(first_coordinate);
371
372 let ring = LineString::new(coordinates);
373
374 let area = shoelace_formula(&ring.clone().into_points());
375
376 if area > 0.0 {
377 if !linestrings.is_empty() {
379 polygons.push(Polygon::new(
381 linestrings[0].clone(),
382 linestrings[1..].into(),
383 ));
384 linestrings = Vec::new();
385 }
386 }
387
388 linestrings.push(ring);
389 coordinates = Vec::with_capacity(geometry_data.len());
391 }
392 _ => (),
393 }
394 } else {
395 let parameter_integer = value;
396 let integer_value = ((parameter_integer >> 1) as i32) ^ -((parameter_integer & 1) as i32);
397 if parameter_count % DIMENSION == 0 {
398 cursor[0] = match cursor[0].checked_add(integer_value) {
399 Some(result) => result,
400 None => i32::MAX, };
402 } else {
403 cursor[1] = match cursor[1].checked_add(integer_value) {
404 Some(result) => result,
405 None => i32::MAX, };
407 coordinates.push(Coord {
408 x: cursor[0] as f32,
409 y: cursor[1] as f32,
410 });
411 }
412 parameter_count -= 1;
413 }
414 }
415
416 match geom_type {
417 GeomType::Linestring => {
418 if !linestrings.is_empty() {
420 linestrings.push(LineString::new(coordinates));
421 return Ok(MultiLineString::new(linestrings).into());
422 }
423 Ok(LineString::new(coordinates).into())
424 }
425 GeomType::Point => Ok(
426 MultiPoint(
427 coordinates
428 .iter()
429 .map(|coord| Point::new(coord.x, coord.y))
430 .collect(),
431 )
432 .into(),
433 ),
434 GeomType::Polygon => {
435 if !linestrings.is_empty() {
436 polygons.push(Polygon::new(
438 linestrings[0].clone(),
439 linestrings[1..].into(),
440 ));
441 return Ok(MultiPolygon::new(polygons).into());
442 }
443 match polygons.first() {
444 Some(polygon) => Ok(polygon.to_owned().into()),
445 None => Err(error::ParserError::new(error::GeometryError::new())),
446 }
447 }
448 GeomType::Unknown => Err(error::ParserError::new(error::GeometryError::new())),
449 }
450}
451
452#[cfg(feature = "wasm")]
453pub mod wasm {
454
455 use crate::feature::Value;
456 use geojson::{Feature, GeoJson, JsonObject, JsonValue, feature::Id};
457 use serde::ser::{Serialize, SerializeStruct};
458 use serde_wasm_bindgen::Serializer;
459 use wasm_bindgen::prelude::*;
460
461 impl From<Value> for JsonValue {
463 fn from(value: Value) -> Self {
464 match value {
465 Value::Null => JsonValue::Null,
466 Value::Bool(b) => JsonValue::from(b),
467 Value::Int(i) => JsonValue::from(i),
468 Value::UInt(u) => JsonValue::from(u),
469 Value::SInt(s) => JsonValue::from(s),
470 Value::Float(f) => JsonValue::from(f),
471 Value::Double(d) => JsonValue::from(d),
472 Value::String(s) => JsonValue::from(s),
473 }
474 }
475 }
476
477 impl From<super::feature::Feature> for wasm_bindgen::JsValue {
479 fn from(feature: super::feature::Feature) -> Self {
480 let properties: Option<JsonObject> = feature.properties.as_ref().map(|props| {
481 props
482 .clone()
483 .into_iter()
484 .map(|(k, v)| (k, v.into()))
485 .collect()
486 });
487
488 let geojson = GeoJson::Feature(Feature {
489 bbox: None,
490 geometry: Some(feature.get_geometry().into()),
491 id: feature.id.map(|id| Id::Number(id.into())),
492 properties,
493 foreign_members: None,
494 });
495
496 geojson.serialize(&Serializer::json_compatible()).unwrap()
497 }
498 }
499
500 impl From<super::layer::Layer> for wasm_bindgen::JsValue {
502 fn from(layer: super::layer::Layer) -> Self {
503 layer.serialize(&Serializer::json_compatible()).unwrap()
504 }
505 }
506
507 impl Serialize for super::layer::Layer {
508 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
509 where
510 S: serde::ser::Serializer,
511 {
512 let mut state = serializer.serialize_struct("Layer", 5)?;
513 state.serialize_field("layer_index", &self.layer_index)?;
514 state.serialize_field("version", &self.version)?;
515 state.serialize_field("name", &self.name)?;
516 state.serialize_field("feature_count", &self.feature_count)?;
517 state.serialize_field("extent", &self.extent)?;
518 state.end()
519 }
520 }
521
522 #[wasm_bindgen]
524 pub struct Reader {
525 reader: Option<super::Reader>,
526 }
527
528 #[wasm_bindgen]
529 impl Reader {
530 #[wasm_bindgen(constructor)]
544 pub fn new(data: Vec<u8>, error_callback: Option<js_sys::Function>) -> Reader {
545 let reader = match super::Reader::new(data) {
546 Ok(reader) => Some(reader),
547 Err(error) => {
548 if let Some(callback) = error_callback {
549 callback
550 .call1(&JsValue::NULL, &JsValue::from_str(&format!("{:?}", error)))
551 .unwrap();
552 }
553 None
554 }
555 };
556 Reader { reader }
557 }
558
559 #[wasm_bindgen(js_name = getLayerNames)]
578 pub fn get_layer_names(&self, error_callback: Option<js_sys::Function>) -> JsValue {
579 self.handle_result(|reader| reader.get_layer_names(), error_callback)
580 }
581
582 #[wasm_bindgen(js_name = getLayerMetadata)]
601 pub fn get_layer_metadata(&self, error_callback: Option<js_sys::Function>) -> JsValue {
602 self.handle_result(|reader| reader.get_layer_metadata(), error_callback)
603 }
604
605 #[wasm_bindgen(js_name = getFeatures)]
625 pub fn get_features(
626 &self,
627 layer_index: usize,
628 error_callback: Option<js_sys::Function>,
629 ) -> JsValue {
630 self.handle_result(|reader| reader.get_features(layer_index), error_callback)
631 }
632
633 fn handle_result<T, F>(&self, operation: F, error_callback: Option<js_sys::Function>) -> JsValue
634 where
635 T: IntoIterator,
636 T::Item: Into<JsValue>,
637 F: FnOnce(&super::Reader) -> Result<T, super::error::ParserError>,
638 {
639 match &self.reader {
640 Some(reader) => match operation(reader) {
641 Ok(result) => result
642 .into_iter()
643 .map(Into::into)
644 .collect::<js_sys::Array>()
645 .into(),
646 Err(error) => {
647 if let Some(callback) = error_callback {
648 callback
649 .call1(&JsValue::NULL, &JsValue::from_str(&format!("{:?}", error)))
650 .unwrap();
651 }
652 JsValue::NULL
653 }
654 },
655 None => JsValue::NULL,
656 }
657 }
658 }
659}