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 let tile = Tile::decode(Bytes::from(data))?;
112 Ok(Self { tile })
113 }
114
115 pub fn get_layer_names(&self) -> Result<Vec<String>, error::ParserError> {
141 process_layers(&self.tile.layers, |layer, _| layer.name.clone())
142 }
143
144 pub fn get_layer_metadata(&self) -> Result<Vec<Layer>, error::ParserError> {
171 process_layers(&self.tile.layers, |layer, index| Layer {
172 layer_index: index,
173 version: layer.version,
174 name: layer.name.clone(),
175 feature_count: layer.features.len(),
176 extent: layer.extent.unwrap_or(4096),
177 })
178 }
179
180 pub fn get_features(&self, layer_index: usize) -> Result<Vec<Feature>, error::ParserError> {
210 self.get_features_as::<f32>(layer_index)
211 }
212
213 pub fn get_features_as<T: CoordNum>(&self, layer_index: usize) -> Result<Vec<Feature<T>>, error::ParserError> {
245 let layer = self.tile.layers.get(layer_index);
246 match layer {
247 Some(layer) => {
248 let mut features = Vec::with_capacity(layer.features.len());
249 for feature in layer.features.iter() {
250 if let Some(geom_type) = feature.r#type {
251 let geom_type = GeomType::try_from(geom_type).map_err(|_| error::ParserError::InvalidGeometry)?;
252 let parsed_geometry = parse_geometry::<T>(&feature.geometry, geom_type)?;
253 let parsed_tags = parse_tags(&feature.tags, &layer.keys, &layer.values)?;
254
255 features.push(Feature {
256 geometry: parsed_geometry,
257 id: feature.id,
258 properties: Some(parsed_tags),
259 });
260 }
261 }
262 Ok(features)
263 }
264 None => Ok(vec![]),
265 }
266 }
267}
268
269fn process_layers<T, F>(
270 layers: &[vector_tile::tile::Layer],
271 mut processor: F,
272) -> Result<Vec<T>, error::ParserError>
273where
274 F: FnMut(&vector_tile::tile::Layer, usize) -> T,
275{
276 let mut results = Vec::with_capacity(layers.len());
277 for (index, layer) in layers.iter().enumerate() {
278 match layer.version {
279 1 | 2 => results.push(processor(layer, index)),
280 _ => {
281 return Err(error::ParserError::UnsupportedVersion {
282 layer_name: layer.name.clone(),
283 version: layer.version,
284 });
285 }
286 }
287 }
288 Ok(results)
289}
290
291fn parse_tags(
292 tags: &[u32],
293 keys: &[String],
294 values: &[vector_tile::tile::Value],
295) -> Result<std::collections::HashMap<String, Value>, error::ParserError> {
296 let mut result = std::collections::HashMap::new();
297 for item in tags.chunks(2) {
298 if item.len() != 2
299 || item[0] as usize >= keys.len()
300 || item[1] as usize >= values.len()
301 {
302 return Err(error::ParserError::InvalidTags);
303 }
304 result.insert(
305 keys[item[0] as usize].clone(),
306 map_value(values[item[1] as usize].clone()),
307 );
308 }
309 Ok(result)
310}
311
312fn map_value(value: vector_tile::tile::Value) -> Value {
313 if let Some(s) = value.string_value {
314 return Value::String(s);
315 }
316 if let Some(f) = value.float_value {
317 return Value::Float(f);
318 }
319 if let Some(d) = value.double_value {
320 return Value::Double(d);
321 }
322 if let Some(i) = value.int_value {
323 return Value::Int(i);
324 }
325 if let Some(u) = value.uint_value {
326 return Value::UInt(u);
327 }
328 if let Some(s) = value.sint_value {
329 return Value::SInt(s);
330 }
331 if let Some(b) = value.bool_value {
332 return Value::Bool(b);
333 }
334 Value::Null
335}
336
337fn shoelace_formula<T: CoordNum>(points: &[Point<T>]) -> f32 {
338 let mut area: f32 = 0.0;
339 let n = points.len();
340 let mut v1 = points[n - 1];
341 for v2 in points.iter().take(n) {
342 let v2y: f32 = NumCast::from(v2.y()).unwrap_or(0.0);
343 let v1y: f32 = NumCast::from(v1.y()).unwrap_or(0.0);
344 let v2x: f32 = NumCast::from(v2.x()).unwrap_or(0.0);
345 let v1x: f32 = NumCast::from(v1.x()).unwrap_or(0.0);
346 area += (v2y - v1y) * (v2x + v1x);
347 v1 = *v2;
348 }
349 area * 0.5
350}
351
352fn parse_geometry<T: CoordNum>(
353 geometry_data: &[u32],
354 geom_type: GeomType,
355) -> Result<Geometry<T>, error::ParserError> {
356 if geom_type == GeomType::Unknown {
357 return Err(error::ParserError::InvalidGeometry);
358 }
359
360 let mut coordinates: Vec<Coord<T>> = Vec::with_capacity(geometry_data.len());
362 let mut polygons: Vec<Polygon<T>> = Vec::new();
363 let mut linestrings: Vec<LineString<T>> = Vec::new();
364
365 let mut cursor: [i32; 2] = [0, 0];
366 let mut parameter_count: u32 = 0;
367
368 for value in geometry_data.iter() {
369 if parameter_count == 0 {
370 let command_integer = value;
371 let id = (command_integer & 0x7) as u8;
372 match id {
373 1 => {
374 parameter_count = (command_integer >> 3) * DIMENSION;
376 if geom_type == GeomType::Linestring && !coordinates.is_empty() {
377 linestrings.push(LineString::new(coordinates));
378 coordinates = Vec::with_capacity(geometry_data.len());
380 }
381 }
382 2 => {
383 parameter_count = (command_integer >> 3) * DIMENSION;
385 }
386 7 => {
387 let first_coordinate = match coordinates.first() {
389 Some(coord) => coord.to_owned(),
390 None => {
391 return Err(error::ParserError::InvalidGeometry);
392 }
393 };
394 coordinates.push(first_coordinate);
395
396 let ring = LineString::new(coordinates);
397
398 let area = shoelace_formula(&ring.clone().into_points());
399
400 if area > 0.0 {
401 if !linestrings.is_empty() {
403 polygons.push(Polygon::new(
405 linestrings[0].clone(),
406 linestrings[1..].into(),
407 ));
408 linestrings = Vec::new();
409 }
410 }
411
412 linestrings.push(ring);
413 coordinates = Vec::with_capacity(geometry_data.len());
415 }
416 _ => (),
417 }
418 } else {
419 let parameter_integer = value;
420 let integer_value = ((parameter_integer >> 1) as i32) ^ -((parameter_integer & 1) as i32);
421 if parameter_count.is_multiple_of(DIMENSION) {
422 cursor[0] = match cursor[0].checked_add(integer_value) {
423 Some(result) => result,
424 None => i32::MAX, };
426 } else {
427 cursor[1] = match cursor[1].checked_add(integer_value) {
428 Some(result) => result,
429 None => i32::MAX, };
431 let x = NumCast::from(cursor[0])
432 .ok_or(error::ParserError::CoordinateOverflow { value: cursor[0] })?;
433 let y = NumCast::from(cursor[1])
434 .ok_or(error::ParserError::CoordinateOverflow { value: cursor[1] })?;
435 coordinates.push(Coord { x, y });
436 }
437 parameter_count -= 1;
438 }
439 }
440
441 match geom_type {
442 GeomType::Linestring => {
443 if !linestrings.is_empty() {
445 linestrings.push(LineString::new(coordinates));
446 return Ok(MultiLineString::new(linestrings).into());
447 }
448 Ok(LineString::new(coordinates).into())
449 }
450 GeomType::Point => Ok(
451 MultiPoint(
452 coordinates
453 .iter()
454 .map(|coord| Point::new(coord.x, coord.y))
455 .collect(),
456 )
457 .into(),
458 ),
459 GeomType::Polygon => {
460 if !linestrings.is_empty() {
461 polygons.push(Polygon::new(
463 linestrings[0].clone(),
464 linestrings[1..].into(),
465 ));
466 return Ok(MultiPolygon::new(polygons).into());
467 }
468 match polygons.first() {
469 Some(polygon) => Ok(polygon.to_owned().into()),
470 None => Err(error::ParserError::InvalidGeometry),
471 }
472 }
473 GeomType::Unknown => Err(error::ParserError::InvalidGeometry),
474 }
475}
476
477#[cfg(feature = "wasm")]
478pub mod wasm {
479
480 use crate::feature::Value;
481 use geojson::{Feature, GeoJson, JsonObject, JsonValue, feature::Id};
482 use serde::ser::{Serialize, SerializeStruct};
483 use serde_wasm_bindgen::Serializer;
484 use wasm_bindgen::prelude::*;
485
486 impl From<Value> for JsonValue {
488 fn from(value: Value) -> Self {
489 match value {
490 Value::Null => JsonValue::Null,
491 Value::Bool(b) => JsonValue::from(b),
492 Value::Int(i) => JsonValue::from(i),
493 Value::UInt(u) => JsonValue::from(u),
494 Value::SInt(s) => JsonValue::from(s),
495 Value::Float(f) => JsonValue::from(f),
496 Value::Double(d) => JsonValue::from(d),
497 Value::String(s) => JsonValue::from(s),
498 }
499 }
500 }
501
502 impl From<super::feature::Feature> for wasm_bindgen::JsValue {
504 fn from(feature: super::feature::Feature) -> Self {
505 let properties: Option<JsonObject> = feature.properties.as_ref().map(|props| {
506 props
507 .clone()
508 .into_iter()
509 .map(|(k, v)| (k, v.into()))
510 .collect()
511 });
512
513 let geojson = GeoJson::Feature(Feature {
514 bbox: None,
515 geometry: Some(feature.get_geometry().into()),
516 id: feature.id.map(|id| Id::Number(id.into())),
517 properties,
518 foreign_members: None,
519 });
520
521 geojson.serialize(&Serializer::json_compatible()).unwrap()
522 }
523 }
524
525 impl From<super::layer::Layer> for wasm_bindgen::JsValue {
527 fn from(layer: super::layer::Layer) -> Self {
528 layer.serialize(&Serializer::json_compatible()).unwrap()
529 }
530 }
531
532 impl Serialize for super::layer::Layer {
533 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
534 where
535 S: serde::ser::Serializer,
536 {
537 let mut state = serializer.serialize_struct("Layer", 5)?;
538 state.serialize_field("layer_index", &self.layer_index)?;
539 state.serialize_field("version", &self.version)?;
540 state.serialize_field("name", &self.name)?;
541 state.serialize_field("feature_count", &self.feature_count)?;
542 state.serialize_field("extent", &self.extent)?;
543 state.end()
544 }
545 }
546
547 #[wasm_bindgen]
549 pub struct Reader {
550 reader: Option<super::Reader>,
551 }
552
553 #[wasm_bindgen]
554 impl Reader {
555 #[wasm_bindgen(constructor)]
569 pub fn new(data: Vec<u8>, error_callback: Option<js_sys::Function>) -> Reader {
570 let reader = match super::Reader::new(data) {
571 Ok(reader) => Some(reader),
572 Err(error) => {
573 if let Some(callback) = error_callback {
574 callback
575 .call1(&JsValue::NULL, &JsValue::from_str(&format!("{:?}", error)))
576 .unwrap();
577 }
578 None
579 }
580 };
581 Reader { reader }
582 }
583
584 #[wasm_bindgen(js_name = getLayerNames)]
603 pub fn get_layer_names(&self, error_callback: Option<js_sys::Function>) -> JsValue {
604 self.handle_result(|reader| reader.get_layer_names(), error_callback)
605 }
606
607 #[wasm_bindgen(js_name = getLayerMetadata)]
626 pub fn get_layer_metadata(&self, error_callback: Option<js_sys::Function>) -> JsValue {
627 self.handle_result(|reader| reader.get_layer_metadata(), error_callback)
628 }
629
630 #[wasm_bindgen(js_name = getFeatures)]
650 pub fn get_features(
651 &self,
652 layer_index: usize,
653 error_callback: Option<js_sys::Function>,
654 ) -> JsValue {
655 self.handle_result(|reader| reader.get_features(layer_index), error_callback)
656 }
657
658 fn handle_result<T, F>(&self, operation: F, error_callback: Option<js_sys::Function>) -> JsValue
659 where
660 T: IntoIterator,
661 T::Item: Into<JsValue>,
662 F: FnOnce(&super::Reader) -> Result<T, super::error::ParserError>,
663 {
664 match &self.reader {
665 Some(reader) => match operation(reader) {
666 Ok(result) => result
667 .into_iter()
668 .map(Into::into)
669 .collect::<js_sys::Array>()
670 .into(),
671 Err(error) => {
672 if let Some(callback) = error_callback {
673 callback
674 .call1(&JsValue::NULL, &JsValue::from_str(&format!("{:?}", error)))
675 .unwrap();
676 }
677 JsValue::NULL
678 }
679 },
680 None => JsValue::NULL,
681 }
682 }
683 }
684}