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