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