1pub mod error;
69pub mod feature;
70pub mod layer;
71
72mod vector_tile;
73
74use feature::{Feature, Value};
75use geo_types::{
76 Coord, CoordNum, Geometry, LineString, MultiLineString, MultiPoint, MultiPolygon, Point, Polygon,
77};
78use layer::Layer;
79use num_traits::NumCast;
80use prost::{Message, bytes::Bytes};
81use vector_tile::{Tile, tile::GeomType};
82
83const DIMENSION: u32 = 2;
85
86pub struct Reader {
88 tile: Tile,
89}
90
91impl Reader {
92 pub fn new(data: Vec<u8>) -> Result<Self, error::ParserError> {
111 match Tile::decode(Bytes::from(data)) {
112 Ok(tile) => Ok(Self { tile }),
113 Err(error) => Err(error::ParserError::new(error::DecodeError::new(Box::new(
114 error,
115 )))),
116 }
117 }
118
119 pub fn get_layer_names(&self) -> Result<Vec<String>, error::ParserError> {
145 process_layers(&self.tile.layers, |layer, _| layer.name.clone())
146 }
147
148 pub fn get_layer_metadata(&self) -> Result<Vec<Layer>, error::ParserError> {
175 process_layers(&self.tile.layers, |layer, index| Layer {
176 layer_index: index,
177 version: layer.version,
178 name: layer.name.clone(),
179 feature_count: layer.features.len(),
180 extent: layer.extent.unwrap_or(4096),
181 })
182 }
183
184 pub fn get_features(&self, layer_index: usize) -> Result<Vec<Feature>, error::ParserError> {
214 self.get_features_as::<f32>(layer_index)
215 }
216
217 pub fn get_features_as<T: CoordNum>(&self, layer_index: usize) -> Result<Vec<Feature<T>>, error::ParserError> {
249 let layer = self.tile.layers.get(layer_index);
250 match layer {
251 Some(layer) => {
252 let mut features = Vec::with_capacity(layer.features.len());
253 for feature in layer.features.iter() {
254 if let Some(geom_type) = feature.r#type {
255 match GeomType::try_from(geom_type) {
256 Ok(geom_type) => {
257 let parsed_geometry = match parse_geometry::<T>(&feature.geometry, geom_type) {
258 Ok(parsed_geometry) => parsed_geometry,
259 Err(error) => {
260 return Err(error);
261 }
262 };
263
264 let parsed_tags = match parse_tags(&feature.tags, &layer.keys, &layer.values) {
265 Ok(parsed_tags) => parsed_tags,
266 Err(error) => {
267 return Err(error);
268 }
269 };
270
271 features.push(Feature {
272 geometry: parsed_geometry,
273 id: feature.id,
274 properties: Some(parsed_tags),
275 });
276 }
277 Err(error) => {
278 return Err(error::ParserError::new(error::DecodeError::new(Box::new(
279 error,
280 ))));
281 }
282 }
283 }
284 }
285 Ok(features)
286 }
287 None => Ok(vec![]),
288 }
289 }
290}
291
292fn process_layers<T, F>(
293 layers: &[vector_tile::tile::Layer],
294 mut processor: F,
295) -> Result<Vec<T>, error::ParserError>
296where
297 F: FnMut(&vector_tile::tile::Layer, usize) -> T,
298{
299 let mut results = Vec::with_capacity(layers.len());
300 for (index, layer) in layers.iter().enumerate() {
301 match layer.version {
302 1 | 2 => results.push(processor(layer, index)),
303 _ => {
304 return Err(error::ParserError::new(error::VersionError::new(
305 layer.name.clone(),
306 layer.version,
307 )));
308 }
309 }
310 }
311 Ok(results)
312}
313
314fn parse_tags(
315 tags: &[u32],
316 keys: &[String],
317 values: &[vector_tile::tile::Value],
318) -> Result<std::collections::HashMap<String, Value>, error::ParserError> {
319 let mut result = std::collections::HashMap::new();
320 for item in tags.chunks(2) {
321 if item.len() != 2
322 || item[0] >= keys.len().try_into().unwrap()
323 || item[1] >= values.len().try_into().unwrap()
324 {
325 return Err(error::ParserError::new(error::TagsError::new()));
326 }
327 result.insert(
328 keys[item[0] as usize].clone(),
329 map_value(values[item[1] as usize].clone()),
330 );
331 }
332 Ok(result)
333}
334
335fn map_value(value: vector_tile::tile::Value) -> Value {
336 if let Some(s) = value.string_value {
337 return Value::String(s);
338 }
339 if let Some(f) = value.float_value {
340 return Value::Float(f);
341 }
342 if let Some(d) = value.double_value {
343 return Value::Double(d);
344 }
345 if let Some(i) = value.int_value {
346 return Value::Int(i);
347 }
348 if let Some(u) = value.uint_value {
349 return Value::UInt(u);
350 }
351 if let Some(s) = value.sint_value {
352 return Value::SInt(s);
353 }
354 if let Some(b) = value.bool_value {
355 return Value::Bool(b);
356 }
357 Value::Null
358}
359
360fn shoelace_formula<T: CoordNum>(points: &[Point<T>]) -> f32 {
361 let mut area: f32 = 0.0;
362 let n = points.len();
363 let mut v1 = points[n - 1];
364 for v2 in points.iter().take(n) {
365 let v2y: f32 = NumCast::from(v2.y()).unwrap_or(0.0);
366 let v1y: f32 = NumCast::from(v1.y()).unwrap_or(0.0);
367 let v2x: f32 = NumCast::from(v2.x()).unwrap_or(0.0);
368 let v1x: f32 = NumCast::from(v1.x()).unwrap_or(0.0);
369 area += (v2y - v1y) * (v2x + v1x);
370 v1 = *v2;
371 }
372 area * 0.5
373}
374
375fn parse_geometry<T: CoordNum>(
376 geometry_data: &[u32],
377 geom_type: GeomType,
378) -> Result<Geometry<T>, error::ParserError> {
379 if geom_type == GeomType::Unknown {
380 return Err(error::ParserError::new(error::GeometryError::new()));
381 }
382
383 let mut coordinates: Vec<Coord<T>> = Vec::with_capacity(geometry_data.len());
385 let mut polygons: Vec<Polygon<T>> = Vec::new();
386 let mut linestrings: Vec<LineString<T>> = Vec::new();
387
388 let mut cursor: [i32; 2] = [0, 0];
389 let mut parameter_count: u32 = 0;
390
391 for value in geometry_data.iter() {
392 if parameter_count == 0 {
393 let command_integer = value;
394 let id = (command_integer & 0x7) as u8;
395 match id {
396 1 => {
397 parameter_count = (command_integer >> 3) * DIMENSION;
399 if geom_type == GeomType::Linestring && !coordinates.is_empty() {
400 linestrings.push(LineString::new(coordinates));
401 coordinates = Vec::with_capacity(geometry_data.len());
403 }
404 }
405 2 => {
406 parameter_count = (command_integer >> 3) * DIMENSION;
408 }
409 7 => {
410 let first_coordinate = match coordinates.first() {
412 Some(coord) => coord.to_owned(),
413 None => {
414 return Err(error::ParserError::new(error::GeometryError::new()));
415 }
416 };
417 coordinates.push(first_coordinate);
418
419 let ring = LineString::new(coordinates);
420
421 let area = shoelace_formula(&ring.clone().into_points());
422
423 if area > 0.0 {
424 if !linestrings.is_empty() {
426 polygons.push(Polygon::new(
428 linestrings[0].clone(),
429 linestrings[1..].into(),
430 ));
431 linestrings = Vec::new();
432 }
433 }
434
435 linestrings.push(ring);
436 coordinates = Vec::with_capacity(geometry_data.len());
438 }
439 _ => (),
440 }
441 } else {
442 let parameter_integer = value;
443 let integer_value = ((parameter_integer >> 1) as i32) ^ -((parameter_integer & 1) as i32);
444 if parameter_count.is_multiple_of(DIMENSION) {
445 cursor[0] = match cursor[0].checked_add(integer_value) {
446 Some(result) => result,
447 None => i32::MAX, };
449 } else {
450 cursor[1] = match cursor[1].checked_add(integer_value) {
451 Some(result) => result,
452 None => i32::MAX, };
454 coordinates.push(Coord {
455 x: NumCast::from(cursor[0]).unwrap_or_else(T::zero),
456 y: NumCast::from(cursor[1]).unwrap_or_else(T::zero),
457 });
458 }
459 parameter_count -= 1;
460 }
461 }
462
463 match geom_type {
464 GeomType::Linestring => {
465 if !linestrings.is_empty() {
467 linestrings.push(LineString::new(coordinates));
468 return Ok(MultiLineString::new(linestrings).into());
469 }
470 Ok(LineString::new(coordinates).into())
471 }
472 GeomType::Point => Ok(
473 MultiPoint(
474 coordinates
475 .iter()
476 .map(|coord| Point::new(coord.x, coord.y))
477 .collect(),
478 )
479 .into(),
480 ),
481 GeomType::Polygon => {
482 if !linestrings.is_empty() {
483 polygons.push(Polygon::new(
485 linestrings[0].clone(),
486 linestrings[1..].into(),
487 ));
488 return Ok(MultiPolygon::new(polygons).into());
489 }
490 match polygons.first() {
491 Some(polygon) => Ok(polygon.to_owned().into()),
492 None => Err(error::ParserError::new(error::GeometryError::new())),
493 }
494 }
495 GeomType::Unknown => Err(error::ParserError::new(error::GeometryError::new())),
496 }
497}
498
499#[cfg(feature = "wasm")]
500pub mod wasm {
501
502 use crate::feature::Value;
503 use geojson::{Feature, GeoJson, JsonObject, JsonValue, feature::Id};
504 use serde::ser::{Serialize, SerializeStruct};
505 use serde_wasm_bindgen::Serializer;
506 use wasm_bindgen::prelude::*;
507
508 impl From<Value> for JsonValue {
510 fn from(value: Value) -> Self {
511 match value {
512 Value::Null => JsonValue::Null,
513 Value::Bool(b) => JsonValue::from(b),
514 Value::Int(i) => JsonValue::from(i),
515 Value::UInt(u) => JsonValue::from(u),
516 Value::SInt(s) => JsonValue::from(s),
517 Value::Float(f) => JsonValue::from(f),
518 Value::Double(d) => JsonValue::from(d),
519 Value::String(s) => JsonValue::from(s),
520 }
521 }
522 }
523
524 impl From<super::feature::Feature> for wasm_bindgen::JsValue {
526 fn from(feature: super::feature::Feature) -> Self {
527 let properties: Option<JsonObject> = feature.properties.as_ref().map(|props| {
528 props
529 .clone()
530 .into_iter()
531 .map(|(k, v)| (k, v.into()))
532 .collect()
533 });
534
535 let geojson = GeoJson::Feature(Feature {
536 bbox: None,
537 geometry: Some(feature.get_geometry().into()),
538 id: feature.id.map(|id| Id::Number(id.into())),
539 properties,
540 foreign_members: None,
541 });
542
543 geojson.serialize(&Serializer::json_compatible()).unwrap()
544 }
545 }
546
547 impl From<super::layer::Layer> for wasm_bindgen::JsValue {
549 fn from(layer: super::layer::Layer) -> Self {
550 layer.serialize(&Serializer::json_compatible()).unwrap()
551 }
552 }
553
554 impl Serialize for super::layer::Layer {
555 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
556 where
557 S: serde::ser::Serializer,
558 {
559 let mut state = serializer.serialize_struct("Layer", 5)?;
560 state.serialize_field("layer_index", &self.layer_index)?;
561 state.serialize_field("version", &self.version)?;
562 state.serialize_field("name", &self.name)?;
563 state.serialize_field("feature_count", &self.feature_count)?;
564 state.serialize_field("extent", &self.extent)?;
565 state.end()
566 }
567 }
568
569 #[wasm_bindgen]
571 pub struct Reader {
572 reader: Option<super::Reader>,
573 }
574
575 #[wasm_bindgen]
576 impl Reader {
577 #[wasm_bindgen(constructor)]
591 pub fn new(data: Vec<u8>, error_callback: Option<js_sys::Function>) -> Reader {
592 let reader = match super::Reader::new(data) {
593 Ok(reader) => Some(reader),
594 Err(error) => {
595 if let Some(callback) = error_callback {
596 callback
597 .call1(&JsValue::NULL, &JsValue::from_str(&format!("{:?}", error)))
598 .unwrap();
599 }
600 None
601 }
602 };
603 Reader { reader }
604 }
605
606 #[wasm_bindgen(js_name = getLayerNames)]
625 pub fn get_layer_names(&self, error_callback: Option<js_sys::Function>) -> JsValue {
626 self.handle_result(|reader| reader.get_layer_names(), error_callback)
627 }
628
629 #[wasm_bindgen(js_name = getLayerMetadata)]
648 pub fn get_layer_metadata(&self, error_callback: Option<js_sys::Function>) -> JsValue {
649 self.handle_result(|reader| reader.get_layer_metadata(), error_callback)
650 }
651
652 #[wasm_bindgen(js_name = getFeatures)]
672 pub fn get_features(
673 &self,
674 layer_index: usize,
675 error_callback: Option<js_sys::Function>,
676 ) -> JsValue {
677 self.handle_result(|reader| reader.get_features(layer_index), error_callback)
678 }
679
680 fn handle_result<T, F>(&self, operation: F, error_callback: Option<js_sys::Function>) -> JsValue
681 where
682 T: IntoIterator,
683 T::Item: Into<JsValue>,
684 F: FnOnce(&super::Reader) -> Result<T, super::error::ParserError>,
685 {
686 match &self.reader {
687 Some(reader) => match operation(reader) {
688 Ok(result) => result
689 .into_iter()
690 .map(Into::into)
691 .collect::<js_sys::Array>()
692 .into(),
693 Err(error) => {
694 if let Some(callback) = error_callback {
695 callback
696 .call1(&JsValue::NULL, &JsValue::from_str(&format!("{:?}", error)))
697 .unwrap();
698 }
699 JsValue::NULL
700 }
701 },
702 None => JsValue::NULL,
703 }
704 }
705 }
706}