1use std::fmt;
20
21use geo_types::Geometry;
22
23use crate::decoder::{Layer01, ParsedLayer01, ParsedProperty, ParsedScalar, RawProperty};
24use crate::{Lazy, LazyParsed, MltResult, Parsed};
25
26pub trait LendingIterator {
41 type Item<'this>
43 where
44 Self: 'this;
45
46 fn next(&mut self) -> Option<Self::Item<'_>>;
48}
49
50impl<'a> Layer01<'a, Lazy> {
51 pub fn iterate_prop_names(&self) -> impl Iterator<Item = PropName<'a>> + '_ {
59 let props = &self.properties;
60 let mut col_idx = 0;
61 let mut dict_idx = 0;
62 std::iter::from_fn(move || {
63 loop {
64 let idx = col_idx;
65 col_idx += 1;
66 let name = match props.get(idx)? {
67 LazyParsed::Raw(r) => raw_col_name(r, &mut dict_idx),
68 LazyParsed::Parsed(p) => parsed_col_name(p, &mut dict_idx),
69 LazyParsed::ParsingFailed => None,
70 };
71 if dict_idx != 0 {
72 col_idx -= 1;
73 }
74 if let Some(n) = name {
75 return Some(n);
76 }
77 }
78 })
79 }
80}
81
82impl<'a> ParsedLayer01<'a> {
83 #[must_use]
102 pub fn iter_features(&self) -> Layer01FeatureIter<'_, 'a> {
103 Layer01FeatureIter::new(self)
104 }
105
106 pub fn iterate_prop_names(&self) -> impl Iterator<Item = PropName<'a>> + '_ {
109 Layer01PropNamesIter::new(&self.properties)
110 }
111}
112
113#[derive(Debug, Clone, Copy)] pub struct PropName<'a>(&'a str, &'a str);
124
125impl fmt::Display for PropName<'_> {
126 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
127 f.write_str(self.0)?;
128 f.write_str(self.1)
129 }
130}
131
132impl PartialEq<PropName<'_>> for PropName<'_> {
133 fn eq(&self, other: &PropName<'_>) -> bool {
134 let (a0, a1) = (self.0.as_bytes(), self.1.as_bytes());
136 let a = a0.iter().chain(a1);
137 let (b0, b1) = (other.0.as_bytes(), other.1.as_bytes());
138 let b = b0.iter().chain(b1);
139 let combined_len_eq = a0.len() + a1.len() == b0.len() + b1.len();
140 combined_len_eq && a.eq(b)
141 }
142}
143
144impl PartialEq<str> for PropName<'_> {
145 fn eq(&self, other: &str) -> bool {
147 other.strip_prefix(self.0) == Some(self.1)
148 }
149}
150
151impl PartialEq<PropName<'_>> for str {
152 fn eq(&self, other: &PropName<'_>) -> bool {
153 other == self
154 }
155}
156
157impl PartialEq<&str> for PropName<'_> {
158 fn eq(&self, other: &&str) -> bool {
159 self == *other
160 }
161}
162
163impl PartialEq<PropName<'_>> for &str {
164 fn eq(&self, other: &PropName<'_>) -> bool {
165 other == *self
166 }
167}
168
169#[derive(Debug, Clone, Copy, PartialEq)]
174pub enum PropValueRef<'a> {
175 Bool(bool),
176 I8(i8),
177 U8(u8),
178 I32(i32),
179 U32(u32),
180 I64(i64),
181 U64(u64),
182 F32(f32),
183 F64(f64),
184 Str(&'a str),
185}
186
187macro_rules! impl_from_for_prop_value_ref {
188 ($($ty:ty => $variant:ident),+ $(,)?) => {
189 $(impl From<$ty> for PropValueRef<'_> {
190 fn from(v: $ty) -> Self { Self::$variant(v) }
191 })+
192 };
193}
194impl_from_for_prop_value_ref!(
195 bool => Bool, i8 => I8, u8 => U8,
196 i32 => I32, u32 => U32,
197 i64 => I64, u64 => U64,
198 f32 => F32, f64 => F64,
199);
200
201#[derive(Debug, Clone, Copy, PartialEq)]
206pub struct ColumnRef<'a> {
207 pub name: PropName<'a>,
208 pub value: PropValueRef<'a>,
209}
210
211#[derive(Debug)]
216pub struct FeatureRef<'feat, 'layer: 'feat> {
217 pub id: Option<u64>,
219 pub geometry: Geometry<i32>,
221 columns: &'layer [ParsedProperty<'layer>],
223 values: &'feat [Option<PropValueRef<'layer>>],
226}
227
228impl<'feat, 'layer: 'feat> FeatureRef<'feat, 'layer> {
229 pub fn iter_all_properties(&self) -> impl Iterator<Item = Option<PropValueRef<'layer>>> + '_ {
237 self.values.iter().copied()
238 }
239
240 pub fn iter_properties(&self) -> impl Iterator<Item = ColumnRef<'layer>> + '_ {
245 Layer01PropNamesIter::new(self.columns)
246 .zip(self.values.iter().copied())
247 .filter_map(|(name, opt_val)| opt_val.map(|value| ColumnRef { name, value }))
248 }
249
250 #[must_use]
255 pub fn get_property(&self, name: &str) -> Option<PropValueRef<'layer>> {
256 self.iter_properties()
257 .find(|col| col.name == name)
258 .map(|col| col.value)
259 }
260}
261
262pub(crate) struct Layer01PropNamesIter<'a, 'p> {
269 props: &'a [ParsedProperty<'p>],
270 col_idx: usize,
271 dict_idx: usize,
272}
273
274impl<'a, 'p> Layer01PropNamesIter<'a, 'p> {
275 pub(crate) fn new(props: &'a [ParsedProperty<'p>]) -> Self {
276 Self {
277 props,
278 col_idx: 0,
279 dict_idx: 0,
280 }
281 }
282}
283
284impl<'a> Iterator for Layer01PropNamesIter<'_, 'a> {
285 type Item = PropName<'a>;
286
287 fn next(&mut self) -> Option<PropName<'a>> {
288 loop {
289 let col_idx = self.col_idx;
290 self.col_idx += 1;
291 let name = parsed_col_name(self.props.get(col_idx)?, &mut self.dict_idx);
292 if self.dict_idx != 0 {
293 self.col_idx -= 1; }
295 if let Some(n) = name {
296 return Some(n);
297 }
298 }
299 }
300}
301
302#[inline]
304fn parsed_col_name<'p>(prop: &ParsedProperty<'p>, dict_idx: &mut usize) -> Option<PropName<'p>> {
305 use ParsedProperty as P;
306 match prop {
307 P::Bool(s) => Some(PropName(s.name, "")),
308 P::I8(s) => Some(PropName(s.name, "")),
309 P::U8(s) => Some(PropName(s.name, "")),
310 P::I32(s) => Some(PropName(s.name, "")),
311 P::U32(s) => Some(PropName(s.name, "")),
312 P::I64(s) => Some(PropName(s.name, "")),
313 P::U64(s) => Some(PropName(s.name, "")),
314 P::F32(s) => Some(PropName(s.name, "")),
315 P::F64(s) => Some(PropName(s.name, "")),
316 P::Str(s) => Some(PropName(s.name, "")),
317 P::SharedDict(sd) => {
318 if *dict_idx < sd.items.len() {
319 let idx = *dict_idx;
320 *dict_idx += 1;
321 Some(PropName(sd.prefix, sd.items[idx].suffix))
322 } else {
323 *dict_idx = 0;
324 None
325 }
326 }
327 }
328}
329
330#[inline]
332fn raw_col_name<'p>(prop: &RawProperty<'p>, dict_idx: &mut usize) -> Option<PropName<'p>> {
333 use RawProperty as P;
334 match prop {
335 P::Bool(s)
336 | P::I8(s)
337 | P::U8(s)
338 | P::I32(s)
339 | P::U32(s)
340 | P::I64(s)
341 | P::U64(s)
342 | P::F32(s)
343 | P::F64(s) => Some(PropName(s.name, "")),
344 P::Str(s) => Some(PropName(s.name, "")),
345 P::SharedDict(sd) => {
346 if *dict_idx < sd.children.len() {
347 let idx = *dict_idx;
348 *dict_idx += 1;
349 Some(PropName(sd.name, sd.children[idx].name))
350 } else {
351 *dict_idx = 0;
352 None
353 }
354 }
355 }
356}
357
358type ColValIter<'l> = Box<dyn Iterator<Item = Option<PropValueRef<'l>>> + 'l>;
360
361fn build_col_iters<'p>(columns: &'p [ParsedProperty<'p>]) -> Vec<ColValIter<'p>> {
366 use ParsedProperty as PP;
367 let mut iters: Vec<ColValIter<'p>> = Vec::new();
368 for col in columns {
369 match col {
370 PP::Bool(s) => iters.push(scalar_col_iter(s)),
371 PP::I8(s) => iters.push(scalar_col_iter(s)),
372 PP::U8(s) => iters.push(scalar_col_iter(s)),
373 PP::I32(s) => iters.push(scalar_col_iter(s)),
374 PP::U32(s) => iters.push(scalar_col_iter(s)),
375 PP::I64(s) => iters.push(scalar_col_iter(s)),
376 PP::U64(s) => iters.push(scalar_col_iter(s)),
377 PP::F32(s) => iters.push(scalar_col_iter(s)),
378 PP::F64(s) => iters.push(scalar_col_iter(s)),
379 PP::Str(strings) => {
380 let data: &'p str = strings.data.as_ref();
381 let lengths: &'p [i32] = &strings.lengths;
382 let mut curr_end: u32 = 0;
383 let mut feat_idx = 0usize;
384 iters.push(Box::new(std::iter::from_fn(move || {
385 let &end_i32 = lengths.get(feat_idx)?;
386 feat_idx += 1;
387 if end_i32 >= 0 {
388 let start = curr_end as usize;
389 curr_end = end_i32.cast_unsigned();
390 Some(data.get(start..curr_end as usize).map(PropValueRef::Str))
391 } else {
392 Some(None)
394 }
395 })));
396 }
397 PP::SharedDict(dict) => {
398 for item in &dict.items {
399 let dict_ref: &'p _ = dict;
400 let item_ref: &'p _ = item;
401 let mut feat_idx = 0usize;
402 iters.push(Box::new(std::iter::from_fn(move || {
403 if feat_idx >= item_ref.ranges.len() {
404 return None;
405 }
406 let idx = feat_idx;
407 feat_idx += 1;
408 Some(item_ref.get(dict_ref, idx).map(PropValueRef::Str))
409 })));
410 }
411 }
412 }
413 }
414 iters
415}
416
417fn scalar_col_iter<'p, T>(scalar: &'p ParsedScalar<'p, T>) -> ColValIter<'p>
419where
420 T: Copy + PartialEq,
421 PropValueRef<'p>: From<T>,
422{
423 Box::new(scalar.iter_optional().map(|o| o.map(PropValueRef::from)))
424}
425
426pub struct Layer01FeatureIter<'layer, 'data: 'layer> {
436 layer: &'layer Layer01<'data, Parsed>,
437 index: usize,
438 feature_count: usize,
439 id_iter: Option<crate::utils::PresenceOptIter<'layer, u64>>,
441 col_iters: Vec<ColValIter<'layer>>,
443 values_buf: Vec<Option<PropValueRef<'layer>>>,
445}
446
447impl<'layer, 'data: 'layer> Layer01FeatureIter<'layer, 'data> {
448 fn new(layer: &'layer Layer01<'data, Parsed>) -> Self {
449 let col_iters = build_col_iters(&layer.properties);
450 let cap = col_iters.len();
451 Self {
452 layer,
453 index: 0,
454 feature_count: layer.feature_count(),
455 id_iter: layer.id.as_ref().map(|id| id.iter_optional()),
456 col_iters,
457 values_buf: Vec::with_capacity(cap),
458 }
459 }
460
461 #[must_use]
463 pub fn len(&self) -> usize {
464 self.feature_count - self.index
465 }
466
467 #[must_use]
469 pub fn is_empty(&self) -> bool {
470 self.index >= self.feature_count
471 }
472}
473
474impl<'layer> LendingIterator for Layer01FeatureIter<'layer, '_> {
475 type Item<'this>
476 = MltResult<FeatureRef<'this, 'layer>>
477 where
478 Self: 'this;
479
480 fn next(&mut self) -> Option<Self::Item<'_>> {
481 let index = self.index;
482 if index >= self.feature_count {
483 return None;
484 }
485 self.index += 1;
486
487 let id = self.id_iter.as_mut().and_then(Iterator::next).flatten();
490 self.values_buf.clear();
491 self.values_buf
492 .extend(self.col_iters.iter_mut().map(|it| it.next().flatten()));
493
494 Some(
495 self.layer
496 .geometry
497 .to_geojson(index)
498 .map(|geometry| FeatureRef {
499 id,
500 geometry,
501 columns: &self.layer.properties,
502 values: &self.values_buf,
503 }),
504 )
505 }
506}
507
508#[cfg(test)]
509mod tests {
510 use geo_types::Point;
511 use serde_json::Value;
512
513 use super::*;
514 use crate::Layer;
515 use crate::decoder::GeometryValues;
516 use crate::encoder::model::StagedLayer;
517 use crate::encoder::{Codecs, Encoder, Presence, StagedId, StagedProperty, StagedSharedDict};
518 use crate::test_helpers::{dec, parser};
519
520 fn layer_buf(staged: StagedLayer) -> Vec<u8> {
521 staged
522 .encode_into(Encoder::default(), &mut Codecs::default())
523 .unwrap()
524 .into_layer_bytes()
525 .unwrap()
526 }
527
528 fn three_points() -> GeometryValues {
529 let mut g = GeometryValues::default();
530 g.push_geom(&Geometry::<i32>::Point(Point::new(1, 2)));
531 g.push_geom(&Geometry::<i32>::Point(Point::new(3, 4)));
532 g.push_geom(&Geometry::<i32>::Point(Point::new(5, 6)));
533 g
534 }
535
536 fn empty_layer(name: &str) -> StagedLayer {
537 StagedLayer {
538 name: name.to_string(),
539 extent: 4096,
540 id: StagedId::None,
541 geometry: GeometryValues::default(),
542 properties: vec![],
543 }
544 }
545
546 #[test]
547 fn prop_name_display_concatenates_parts() {
548 assert_eq!(PropName("addr:", "city").to_string(), "addr:city");
549 assert_eq!(PropName("name", "").to_string(), "name");
550 assert_eq!(PropName("", "").to_string(), "");
551 }
552
553 #[test]
554 fn prop_name_eq_str_matches_concatenation() {
555 assert_eq!(PropName("addr:", "city"), "addr:city");
556 assert_eq!("addr:city", PropName("addr:", "city"));
557 assert_ne!(PropName("addr:", "city"), "addr:");
558 assert_ne!(PropName("addr:", "city"), "city");
559 assert_eq!(PropName("name", ""), "name");
560 }
561
562 #[test]
563 fn prop_name_structural_eq_is_part_wise() {
564 assert_eq!(PropName("a", "b"), PropName("a", "b"));
565 assert_eq!(PropName("ab", ""), PropName("a", "b"));
566 }
567
568 #[test]
569 fn prop_name_eq_prop_name_semantic_equality() {
570 assert_eq!(PropName("ab", ""), PropName("a", "b"));
571 assert_eq!(PropName("", "ab"), PropName("a", "b"));
572 assert_eq!(PropName("abc", "def"), PropName("ab", "cdef"));
573 assert_eq!(PropName("a", "bcdef"), PropName("abcde", "f"));
574
575 assert_ne!(PropName("a", "b"), PropName("a", "c"));
576 assert_ne!(PropName("a", "b"), PropName("ab", "c"));
577 assert_ne!(PropName("abc", ""), PropName("ab", ""));
578 }
579
580 #[test]
581 fn prop_value_ref_scalars_convert_to_json() {
582 assert_eq!(Value::from(PropValueRef::Bool(true)), Value::Bool(true));
583 assert_eq!(Value::from(PropValueRef::Bool(false)), Value::Bool(false));
584 assert_eq!(Value::from(PropValueRef::I8(-1)), Value::from(-1_i8));
585 assert_eq!(Value::from(PropValueRef::U8(255)), Value::from(255_u8));
586 assert_eq!(
587 Value::from(PropValueRef::I32(-1000)),
588 Value::from(-1000_i32)
589 );
590 assert_eq!(Value::from(PropValueRef::U32(1000)), Value::from(1000_u32));
591 assert_eq!(
592 Value::from(PropValueRef::I64(i64::MIN)),
593 Value::from(i64::MIN)
594 );
595 assert_eq!(
596 Value::from(PropValueRef::U64(u64::MAX)),
597 Value::from(u64::MAX)
598 );
599 assert_eq!(
600 Value::from(PropValueRef::Str("hello")),
601 Value::String("hello".into())
602 );
603 }
604
605 #[test]
606 fn prop_value_ref_float_finite_is_number() {
607 assert!(matches!(
608 Value::from(PropValueRef::F32(1.5)),
609 Value::Number(_)
610 ));
611 assert!(matches!(
612 Value::from(PropValueRef::F64(2.5)),
613 Value::Number(_)
614 ));
615 }
616
617 #[test]
618 fn prop_value_ref_float_non_finite_becomes_string_sentinel() {
619 assert_eq!(
620 Value::from(PropValueRef::F32(f32::NAN)),
621 Value::String("f32::NAN".into())
622 );
623 assert_eq!(
624 Value::from(PropValueRef::F32(f32::INFINITY)),
625 Value::String("f32::INFINITY".into())
626 );
627 assert_eq!(
628 Value::from(PropValueRef::F64(f64::NAN)),
629 Value::String("f64::NAN".into())
630 );
631 assert_eq!(
632 Value::from(PropValueRef::F64(f64::NEG_INFINITY)),
633 Value::String("f64::NEG_INFINITY".into())
634 );
635 }
636
637 #[test]
638 fn empty_layer_yields_no_features() {
639 let buf = layer_buf(empty_layer("empty"));
640 let (_, layer) = Layer::from_bytes(&buf, &mut parser()).unwrap();
641 let Layer::Tag01(lazy) = layer else {
642 panic!("expected Tag01")
643 };
644 let parsed = lazy.decode_all(&mut dec()).unwrap();
645
646 let iter = parsed.iter_features();
647 assert_eq!(iter.len(), 0);
648 assert!(iter.is_empty());
649 assert_eq!(parsed.iter_features().len(), 0);
650 }
651
652 #[test]
653 fn len_decreases_with_each_next() {
654 let buf = layer_buf(StagedLayer {
655 name: "test".into(),
656 extent: 4096,
657 id: StagedId::None,
658 geometry: three_points(),
659 properties: vec![],
660 });
661 let (_, layer) = Layer::from_bytes(&buf, &mut parser()).unwrap();
662 let Layer::Tag01(lazy) = layer else { panic!() };
663 let parsed = lazy.decode_all(&mut dec()).unwrap();
664
665 let mut iter = parsed.iter_features();
666 assert_eq!(iter.len(), 3);
667 iter.next().unwrap().unwrap();
668 assert_eq!(iter.len(), 2);
669 iter.next().unwrap().unwrap();
670 assert_eq!(iter.len(), 1);
671 iter.next().unwrap().unwrap();
672 assert_eq!(iter.len(), 0);
673 assert!(iter.is_empty());
674 assert!(iter.next().is_none());
675 }
676
677 #[test]
678 fn feature_ids_are_preserved() {
679 let buf = layer_buf(StagedLayer {
680 name: "test".into(),
681 extent: 4096,
682 id: StagedId::from_optional(vec![Some(100), None, Some(200)]),
683 geometry: three_points(),
684 properties: vec![],
685 });
686 let (_, layer) = Layer::from_bytes(&buf, &mut parser()).unwrap();
687 let Layer::Tag01(lazy) = layer else { panic!() };
688 let parsed = lazy.decode_all(&mut dec()).unwrap();
689
690 let mut ids = Vec::new();
691 let mut iter = parsed.iter_features();
692 while let Some(r) = iter.next() {
693 ids.push(r.unwrap().id);
694 }
695 assert_eq!(ids, [Some(100), None, Some(200)]);
696 }
697
698 #[test]
699 fn geometry_values_match_input() {
700 let buf = layer_buf(StagedLayer {
701 name: "test".into(),
702 extent: 4096,
703 id: StagedId::None,
704 geometry: three_points(),
705 properties: vec![],
706 });
707 let (_, layer) = Layer::from_bytes(&buf, &mut parser()).unwrap();
708 let Layer::Tag01(lazy) = layer else { panic!() };
709 let parsed = lazy.decode_all(&mut dec()).unwrap();
710
711 let mut geoms = Vec::new();
712 let mut iter = parsed.iter_features();
713 while let Some(r) = iter.next() {
714 geoms.push(r.unwrap().geometry);
715 }
716 assert_eq!(geoms[0], Geometry::<i32>::Point(Point::new(1, 2)));
717 assert_eq!(geoms[1], Geometry::<i32>::Point(Point::new(3, 4)));
718 assert_eq!(geoms[2], Geometry::<i32>::Point(Point::new(5, 6)));
719 }
720
721 #[test]
722 fn null_scalar_values_are_skipped() {
723 let buf = layer_buf(StagedLayer {
724 name: "test".into(),
725 extent: 4096,
726 id: StagedId::None,
727 geometry: three_points(),
728 properties: vec![StagedProperty::opt_u32("n", vec![Some(1), None, Some(3)])],
729 });
730 let (_, layer) = Layer::from_bytes(&buf, &mut parser()).unwrap();
731 let Layer::Tag01(lazy) = layer else { panic!() };
732 let parsed = lazy.decode_all(&mut dec()).unwrap();
733
734 let mut iter = parsed.iter_features();
735
736 {
737 let feat = iter.next().unwrap().unwrap();
738 let cols: Vec<_> = feat.iter_properties().collect();
739 assert_eq!(cols.len(), 1);
740 assert_eq!(cols[0].name, PropName("n", ""));
741 assert_eq!(cols[0].name, "n");
742 assert_eq!(cols[0].value, PropValueRef::U32(1));
743 let all: Vec<_> = feat.iter_all_properties().collect();
744 assert_eq!(all, [Some(PropValueRef::U32(1))]);
745 }
746 {
747 let feat = iter.next().unwrap().unwrap();
748 assert!(feat.iter_properties().next().is_none());
749 let all: Vec<_> = feat.iter_all_properties().collect();
750 assert_eq!(all, [None]);
751 }
752 {
753 let feat = iter.next().unwrap().unwrap();
754 assert_eq!(feat.get_property("n"), Some(PropValueRef::U32(3)));
755 let all: Vec<_> = feat.iter_all_properties().collect();
756 assert_eq!(all, [Some(PropValueRef::U32(3))]);
757 }
758
759 let names: Vec<_> = parsed.iterate_prop_names().map(|n| n.to_string()).collect();
760 assert_eq!(names, ["n"]);
761 }
762
763 #[test]
764 fn null_string_values_are_skipped() {
765 let buf = layer_buf(StagedLayer {
766 name: "test".into(),
767 extent: 4096,
768 id: StagedId::None,
769 geometry: three_points(),
770 properties: vec![StagedProperty::opt_str(
771 "label",
772 vec![Some("foo"), None, Some("bar")],
773 )],
774 });
775 let (_, layer) = Layer::from_bytes(&buf, &mut parser()).unwrap();
776 let Layer::Tag01(lazy) = layer else { panic!() };
777 let parsed = lazy.decode_all(&mut dec()).unwrap();
778
779 let mut iter = parsed.iter_features();
780 {
781 let feat = iter.next().unwrap().unwrap();
782 assert_eq!(feat.get_property("label"), Some(PropValueRef::Str("foo")));
783 }
784 {
785 let feat = iter.next().unwrap().unwrap();
786 assert_eq!(feat.get_property("label"), None);
787 }
788 {
789 let feat = iter.next().unwrap().unwrap();
790 assert_eq!(feat.get_property("label"), Some(PropValueRef::Str("bar")));
791 }
792 }
793
794 #[test]
795 fn multiple_columns_independently_nullable() {
796 let buf = layer_buf(StagedLayer {
797 name: "test".into(),
798 extent: 4096,
799 id: StagedId::None,
800 geometry: three_points(),
801 properties: vec![
802 StagedProperty::opt_bool("flag", vec![Some(true), Some(false), None]),
803 StagedProperty::opt_i32("score", vec![None, Some(-5), Some(7)]),
804 ],
805 });
806 let (_, layer) = Layer::from_bytes(&buf, &mut parser()).unwrap();
807 let Layer::Tag01(lazy) = layer else { panic!() };
808 let parsed = lazy.decode_all(&mut dec()).unwrap();
809
810 let mut iter = parsed.iter_features();
811
812 {
814 let feat = iter.next().unwrap().unwrap();
815 assert_eq!(feat.iter_properties().count(), 1);
816 assert_eq!(feat.get_property("flag"), Some(PropValueRef::Bool(true)));
817 assert_eq!(feat.get_property("score"), None);
818 }
819 {
821 let feat = iter.next().unwrap().unwrap();
822 assert_eq!(feat.iter_properties().count(), 2);
823 assert_eq!(feat.get_property("flag"), Some(PropValueRef::Bool(false)));
824 assert_eq!(feat.get_property("score"), Some(PropValueRef::I32(-5)));
825 }
826 {
828 let feat = iter.next().unwrap().unwrap();
829 assert_eq!(feat.iter_properties().count(), 1);
830 assert_eq!(feat.get_property("flag"), None);
831 assert_eq!(feat.get_property("score"), Some(PropValueRef::I32(7)));
832 }
833 }
834
835 #[test]
836 fn geometry_error_does_not_misalign_ids() {
837 use crate::decoder::GeometryType;
838
839 let buf = layer_buf(StagedLayer {
840 name: "test".into(),
841 extent: 4096,
842 id: StagedId::from_optional(vec![Some(10), Some(20), Some(30)]),
843 geometry: three_points(),
844 properties: vec![],
845 });
846 let (_, layer) = Layer::from_bytes(&buf, &mut parser()).unwrap();
847 let Layer::Tag01(lazy) = layer else { panic!() };
848 let mut parsed = lazy.decode_all(&mut dec()).unwrap();
849
850 parsed.geometry.vector_types[1] = GeometryType::LineString;
854
855 let mut iter = parsed.iter_features();
856
857 let feat0 = iter.next().unwrap().unwrap();
859 assert_eq!(feat0.id, Some(10));
860
861 assert!(iter.next().unwrap().is_err());
863
864 let feat2 = iter.next().unwrap().unwrap();
866 assert_eq!(
867 feat2.id,
868 Some(30),
869 "id cursor was not advanced on geometry error"
870 );
871
872 assert!(iter.next().is_none());
873 }
874
875 #[test]
876 fn get_property_absent_column_returns_none() {
877 let buf = layer_buf(StagedLayer {
878 name: "test".into(),
879 extent: 4096,
880 id: StagedId::None,
881 geometry: three_points(),
882 properties: vec![StagedProperty::u32("x", vec![1, 2, 3])],
883 });
884 let (_, layer) = Layer::from_bytes(&buf, &mut parser()).unwrap();
885 let Layer::Tag01(lazy) = layer else { panic!() };
886 let parsed = lazy.decode_all(&mut dec()).unwrap();
887
888 let mut iter = parsed.iter_features();
889 let feat = iter.next().unwrap().unwrap();
890 assert_eq!(feat.get_property("no_such_column"), None);
891 }
892
893 #[test]
894 fn shared_dict_columns_are_expanded() {
895 let shared_dict = StagedSharedDict::new(
896 "addr:",
897 [
898 (
899 "city",
900 vec![Some("Paris"), Some("Rome"), None],
901 Presence::Mixed,
902 ),
903 (
904 "zip",
905 vec![Some("75001"), None, Some("00100")],
906 Presence::Mixed,
907 ),
908 ],
909 )
910 .unwrap();
911
912 let buf = layer_buf(StagedLayer {
913 name: "test".into(),
914 extent: 4096,
915 id: StagedId::None,
916 geometry: three_points(),
917 properties: vec![StagedProperty::SharedDict(shared_dict)],
918 });
919 let (_, layer) = Layer::from_bytes(&buf, &mut parser()).unwrap();
920 let Layer::Tag01(lazy) = layer else { panic!() };
921 let parsed = lazy.decode_all(&mut dec()).unwrap();
922
923 let mut iter = parsed.iter_features();
924
925 {
927 let feat = iter.next().unwrap().unwrap();
928 assert_eq!(
929 feat.get_property("addr:city"),
930 Some(PropValueRef::Str("Paris"))
931 );
932 assert_eq!(
933 feat.get_property("addr:zip"),
934 Some(PropValueRef::Str("75001"))
935 );
936 assert_eq!(feat.iter_properties().count(), 2);
937 }
938 {
940 let feat = iter.next().unwrap().unwrap();
941 assert_eq!(
942 feat.get_property("addr:city"),
943 Some(PropValueRef::Str("Rome"))
944 );
945 assert_eq!(feat.get_property("addr:zip"), None);
946 assert_eq!(feat.iter_properties().count(), 1);
947 let all: Vec<_> = feat.iter_all_properties().collect();
949 assert_eq!(all, [Some(PropValueRef::Str("Rome")), None]);
950 }
951 {
953 let feat = iter.next().unwrap().unwrap();
954 assert_eq!(feat.get_property("addr:city"), None);
955 assert_eq!(
956 feat.get_property("addr:zip"),
957 Some(PropValueRef::Str("00100"))
958 );
959 }
960
961 let names: Vec<_> = parsed.iterate_prop_names().map(|n| n.to_string()).collect();
962 assert_eq!(names, ["addr:city", "addr:zip"]);
963 }
964}