1use std::fmt;
20use std::iter::FusedIterator;
21use std::ops::Range;
22
23use geo_types::Geometry;
24use usize_cast::IntoUsize as _;
25
26use crate::decoder::{Layer01, ParsedLayer01, ParsedProperty, ParsedScalar, Property, RawProperty};
27use crate::{Lazy, LazyParsed, MltResult, Parsed};
28
29pub trait LendingIterator {
44 type Item<'this>
46 where
47 Self: 'this;
48
49 fn next(&mut self) -> Option<Self::Item<'_>>;
51}
52
53impl<'a> Layer01<'a, Lazy> {
54 pub fn iterate_prop_names(&self) -> PropNamesIter<'_, Property<'a, Lazy>> {
62 PropNamesIter::new(&self.properties)
63 }
64}
65
66impl<'a> ParsedLayer01<'a> {
67 #[must_use]
86 pub fn iter_features(&self) -> Layer01FeatureIter<'_, 'a> {
87 Layer01FeatureIter::new(self)
88 }
89
90 pub fn iterate_prop_names(&self) -> PropNamesIter<'_, ParsedProperty<'a>> {
93 PropNamesIter::new(&self.properties)
94 }
95}
96
97#[derive(Debug, Clone, Copy)] pub struct PropName<'a>(&'a str, &'a str);
108
109impl fmt::Display for PropName<'_> {
110 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
111 f.write_str(self.0)?;
112 f.write_str(self.1)
113 }
114}
115
116impl PartialEq<PropName<'_>> for PropName<'_> {
117 fn eq(&self, other: &PropName<'_>) -> bool {
118 let (a0, a1) = (self.0.as_bytes(), self.1.as_bytes());
120 let a = a0.iter().chain(a1);
121 let (b0, b1) = (other.0.as_bytes(), other.1.as_bytes());
122 let b = b0.iter().chain(b1);
123 let combined_len_eq = a0.len() + a1.len() == b0.len() + b1.len();
124 combined_len_eq && a.eq(b)
125 }
126}
127
128impl PartialEq<str> for PropName<'_> {
129 fn eq(&self, other: &str) -> bool {
131 other.strip_prefix(self.0) == Some(self.1)
132 }
133}
134
135impl PartialEq<PropName<'_>> for str {
136 fn eq(&self, other: &PropName<'_>) -> bool {
137 other == self
138 }
139}
140
141impl PartialEq<&str> for PropName<'_> {
142 fn eq(&self, other: &&str) -> bool {
143 self == *other
144 }
145}
146
147impl PartialEq<PropName<'_>> for &str {
148 fn eq(&self, other: &PropName<'_>) -> bool {
149 other == *self
150 }
151}
152
153#[derive(Debug, Clone, Copy, PartialEq)]
158pub enum PropValueRef<'a> {
159 Bool(bool),
160 I8(i8),
161 U8(u8),
162 I32(i32),
163 U32(u32),
164 I64(i64),
165 U64(u64),
166 F32(f32),
167 F64(f64),
168 Str(&'a str),
169}
170
171macro_rules! impl_from_for_prop_value_ref {
172 ($($ty:ty => $variant:ident),+ $(,)?) => {
173 $(impl From<$ty> for PropValueRef<'_> {
174 fn from(v: $ty) -> Self { Self::$variant(v) }
175 })+
176 };
177}
178impl_from_for_prop_value_ref!(
179 bool => Bool, i8 => I8, u8 => U8,
180 i32 => I32, u32 => U32,
181 i64 => I64, u64 => U64,
182 f32 => F32, f64 => F64,
183);
184
185#[derive(Debug, Clone, Copy, PartialEq)]
190pub struct ColumnRef<'a> {
191 name: PropName<'a>,
192 value: PropValueRef<'a>,
193}
194
195impl<'a> ColumnRef<'a> {
196 #[must_use]
197 pub fn name(&self) -> PropName<'a> {
198 self.name
199 }
200
201 #[must_use]
202 pub fn value(&self) -> PropValueRef<'a> {
203 self.value
204 }
205}
206
207#[derive(Debug)]
212pub struct FeatureRef<'feat, 'layer: 'feat> {
213 id: Option<u64>,
215 geometry: Geometry<i32>,
217 columns: &'layer [ParsedProperty<'layer>],
219 values: &'feat [Option<PropValueRef<'layer>>],
222}
223
224impl<'feat, 'layer: 'feat> FeatureRef<'feat, 'layer> {
225 #[must_use]
226 pub fn id(&self) -> Option<u64> {
227 self.id
228 }
229
230 #[must_use]
231 pub fn geometry(&self) -> &Geometry<i32> {
232 &self.geometry
233 }
234
235 pub fn iter_all_properties(
243 &self,
244 ) -> impl ExactSizeIterator<Item = Option<PropValueRef<'layer>>>
245 + DoubleEndedIterator
246 + FusedIterator
247 + '_ {
248 self.values.iter().copied()
249 }
250
251 pub fn iter_properties(
256 &self,
257 ) -> impl DoubleEndedIterator<Item = ColumnRef<'layer>> + FusedIterator + '_ {
258 PropNamesIter::new(self.columns)
259 .zip(self.values.iter().copied())
260 .filter_map(|(name, opt_val)| opt_val.map(|value| ColumnRef { name, value }))
261 }
262
263 #[must_use]
268 pub fn get_property(&self, name: &str) -> Option<PropValueRef<'layer>> {
269 self.iter_properties()
270 .find(|col| col.name() == name)
271 .map(|col| col.value())
272 }
273}
274
275pub trait ColNames {
282 type Name;
286
287 fn name_count(&self) -> usize;
289
290 fn name_at(&self, idx: usize) -> Self::Name;
292}
293
294impl<'p> ColNames for ParsedProperty<'p> {
295 type Name = PropName<'p>;
296
297 fn name_count(&self) -> usize {
298 match self {
299 Self::SharedDict(sd) => sd.items.len(),
300 Self::Bool(_)
301 | Self::I8(_)
302 | Self::U8(_)
303 | Self::I32(_)
304 | Self::U32(_)
305 | Self::I64(_)
306 | Self::U64(_)
307 | Self::F32(_)
308 | Self::F64(_)
309 | Self::Str(_) => 1,
310 }
311 }
312
313 fn name_at(&self, idx: usize) -> PropName<'p> {
314 use ParsedProperty as P;
315 match self {
316 P::Bool(s) => PropName(s.name, ""),
317 P::I8(s) => PropName(s.name, ""),
318 P::U8(s) => PropName(s.name, ""),
319 P::I32(s) => PropName(s.name, ""),
320 P::U32(s) => PropName(s.name, ""),
321 P::I64(s) => PropName(s.name, ""),
322 P::U64(s) => PropName(s.name, ""),
323 P::F32(s) => PropName(s.name, ""),
324 P::F64(s) => PropName(s.name, ""),
325 P::Str(s) => PropName(s.name, ""),
326 P::SharedDict(sd) => PropName(sd.prefix, sd.items[idx].suffix),
327 }
328 }
329}
330
331impl<'p> ColNames for RawProperty<'p> {
332 type Name = PropName<'p>;
333
334 fn name_count(&self) -> usize {
335 match self {
336 Self::SharedDict(sd) => sd.children.len(),
337 Self::Bool(_)
338 | Self::I8(_)
339 | Self::U8(_)
340 | Self::I32(_)
341 | Self::U32(_)
342 | Self::I64(_)
343 | Self::U64(_)
344 | Self::F32(_)
345 | Self::F64(_)
346 | Self::Str(_) => 1,
347 }
348 }
349
350 fn name_at(&self, idx: usize) -> PropName<'p> {
351 use RawProperty as P;
352 match self {
353 P::Bool(s) | P::I8(s) | P::U8(s) | P::I32(s) | P::U32(s) | P::I64(s) | P::U64(s) => {
354 PropName(s.name, "")
355 }
356 P::F32(s) | P::F64(s) => PropName(s.name, ""),
357 P::Str(s) => PropName(s.name, ""),
358 P::SharedDict(sd) => PropName(sd.name, sd.children[idx].name),
359 }
360 }
361}
362
363impl<'p> ColNames for LazyParsed<RawProperty<'p>, ParsedProperty<'p>> {
365 type Name = PropName<'p>;
366
367 fn name_count(&self) -> usize {
368 match self {
369 Self::Raw(r) => r.name_count(),
370 Self::Parsed(p) => p.name_count(),
371 Self::ParsingFailed => 0,
372 }
373 }
374
375 fn name_at(&self, idx: usize) -> PropName<'p> {
376 match self {
377 Self::Raw(r) => r.name_at(idx),
378 Self::Parsed(p) => p.name_at(idx),
379 Self::ParsingFailed => unreachable!("ParsingFailed contributes no names"),
380 }
381 }
382}
383
384#[must_use]
389pub struct PropNamesIter<'a, C> {
390 props: &'a [C],
391 cols: Range<usize>,
394 front_sub: usize,
396 back_sub: usize,
398 remaining: usize,
401}
402
403impl<'a, C: ColNames> PropNamesIter<'a, C> {
404 pub(crate) fn new(props: &'a [C]) -> Self {
405 Self {
406 props,
407 cols: 0..props.len(),
408 front_sub: 0,
409 back_sub: props.last().map_or(0, ColNames::name_count),
410 remaining: props.iter().map(ColNames::name_count).sum(),
411 }
412 }
413}
414
415impl<C: ColNames> Iterator for PropNamesIter<'_, C> {
416 type Item = C::Name;
417
418 fn next(&mut self) -> Option<C::Name> {
419 if self.remaining == 0 {
420 return None;
421 }
422 self.remaining -= 1;
423 loop {
424 let col = &self.props[self.cols.start];
426 if self.front_sub < col.name_count() {
427 let name = col.name_at(self.front_sub);
428 self.front_sub += 1;
429 return Some(name);
430 }
431 self.cols.start += 1;
432 self.front_sub = 0;
433 }
434 }
435
436 fn size_hint(&self) -> (usize, Option<usize>) {
437 (self.remaining, Some(self.remaining))
438 }
439}
440
441impl<C: ColNames> DoubleEndedIterator for PropNamesIter<'_, C> {
442 fn next_back(&mut self) -> Option<C::Name> {
443 if self.remaining == 0 {
444 return None;
445 }
446 self.remaining -= 1;
447 loop {
448 if self.back_sub > 0 {
449 self.back_sub -= 1;
450 return Some(self.props[self.cols.end - 1].name_at(self.back_sub));
451 }
452 self.cols.end -= 1;
453 self.back_sub = self.props[self.cols.end - 1].name_count();
454 }
455 }
456}
457
458impl<C: ColNames> ExactSizeIterator for PropNamesIter<'_, C> {
459 fn len(&self) -> usize {
460 self.remaining
461 }
462}
463
464impl<C: ColNames> FusedIterator for PropNamesIter<'_, C> {}
465
466type ColValIter<'l> = Box<dyn Iterator<Item = Option<PropValueRef<'l>>> + 'l>;
468
469fn build_col_iters<'p>(columns: &'p [ParsedProperty<'p>]) -> Vec<ColValIter<'p>> {
474 use ParsedProperty as PP;
475 let mut iters: Vec<ColValIter<'p>> = Vec::new();
476 for col in columns {
477 match col {
478 PP::Bool(s) => iters.push(scalar_col_iter(s)),
479 PP::I8(s) => iters.push(scalar_col_iter(s)),
480 PP::U8(s) => iters.push(scalar_col_iter(s)),
481 PP::I32(s) => iters.push(scalar_col_iter(s)),
482 PP::U32(s) => iters.push(scalar_col_iter(s)),
483 PP::I64(s) => iters.push(scalar_col_iter(s)),
484 PP::U64(s) => iters.push(scalar_col_iter(s)),
485 PP::F32(s) => iters.push(scalar_col_iter(s)),
486 PP::F64(s) => iters.push(scalar_col_iter(s)),
487 PP::Str(strings) => {
488 let data: &'p str = strings.data.as_ref();
489 let lengths: &'p [i32] = &strings.lengths;
490 let mut curr_end: usize = 0;
491 let mut feat_idx = 0usize;
492 iters.push(Box::new(std::iter::from_fn(move || {
493 let &end_i32 = lengths.get(feat_idx)?;
494 feat_idx += 1;
495 if end_i32 >= 0 {
496 let start = curr_end;
497 curr_end = end_i32.cast_unsigned().into_usize();
498 Some(data.get(start..curr_end).map(PropValueRef::Str))
499 } else {
500 Some(None)
502 }
503 })));
504 }
505 PP::SharedDict(dict) => {
506 for item in &dict.items {
507 let dict_ref: &'p _ = dict;
508 let item_ref: &'p _ = item;
509 let mut feat_idx = 0usize;
510 iters.push(Box::new(std::iter::from_fn(move || {
511 if feat_idx >= item_ref.ranges.len() {
512 return None;
513 }
514 let idx = feat_idx;
515 feat_idx += 1;
516 Some(item_ref.get(dict_ref, idx).map(PropValueRef::Str))
517 })));
518 }
519 }
520 }
521 }
522 iters
523}
524
525fn scalar_col_iter<'p, T>(scalar: &'p ParsedScalar<'p, T>) -> ColValIter<'p>
527where
528 T: Copy + PartialEq,
529 PropValueRef<'p>: From<T>,
530{
531 Box::new(scalar.iter_optional().map(|o| o.map(PropValueRef::from)))
532}
533
534pub struct Layer01FeatureIter<'layer, 'data: 'layer> {
544 layer: &'layer Layer01<'data, Parsed>,
545 index: usize,
546 feature_count: usize,
547 id_iter: Option<crate::utils::PresenceOptIter<'layer, u64>>,
549 col_iters: Vec<ColValIter<'layer>>,
551 values_buf: Vec<Option<PropValueRef<'layer>>>,
553}
554
555impl<'layer, 'data: 'layer> Layer01FeatureIter<'layer, 'data> {
556 fn new(layer: &'layer Layer01<'data, Parsed>) -> Self {
557 let col_iters = build_col_iters(&layer.properties);
558 let cap = col_iters.len();
559 Self {
560 layer,
561 index: 0,
562 feature_count: layer.feature_count(),
563 id_iter: layer.id.as_ref().map(|id| id.iter_optional()),
564 col_iters,
565 values_buf: Vec::with_capacity(cap),
566 }
567 }
568
569 #[must_use]
571 pub fn len(&self) -> usize {
572 self.feature_count - self.index
573 }
574
575 #[must_use]
577 pub fn is_empty(&self) -> bool {
578 self.index >= self.feature_count
579 }
580}
581
582impl<'layer> LendingIterator for Layer01FeatureIter<'layer, '_> {
583 type Item<'this>
584 = MltResult<FeatureRef<'this, 'layer>>
585 where
586 Self: 'this;
587
588 fn next(&mut self) -> Option<Self::Item<'_>> {
589 let index = self.index;
590 if index >= self.feature_count {
591 return None;
592 }
593 self.index += 1;
594
595 let id = self.id_iter.as_mut().and_then(Iterator::next).flatten();
598 self.values_buf.clear();
599 self.values_buf
600 .extend(self.col_iters.iter_mut().map(|it| it.next().flatten()));
601
602 Some(
603 self.layer
604 .geometry
605 .to_geojson(index)
606 .map(|geometry| FeatureRef {
607 id,
608 geometry,
609 columns: &self.layer.properties,
610 values: &self.values_buf,
611 }),
612 )
613 }
614}
615
616#[cfg(test)]
617mod tests {
618 use geo_types::Point;
619 use serde_json::Value;
620
621 use super::*;
622 use crate::Layer;
623 use crate::decoder::GeometryValues;
624 use crate::encoder::model::StagedLayer;
625 use crate::encoder::{Codecs, Encoder, Presence, StagedId, StagedProperty, StagedSharedDict};
626 use crate::test_helpers::{assert_size_hint_exact, dec, parser};
627
628 fn layer_buf(staged: StagedLayer) -> Vec<u8> {
629 staged
630 .encode_into(Encoder::default(), &mut Codecs::default())
631 .unwrap()
632 .into_layer_bytes()
633 .unwrap()
634 }
635
636 fn three_points() -> GeometryValues {
637 let mut g = GeometryValues::default();
638 g.push_geom(&Geometry::<i32>::Point(Point::new(1, 2)));
639 g.push_geom(&Geometry::<i32>::Point(Point::new(3, 4)));
640 g.push_geom(&Geometry::<i32>::Point(Point::new(5, 6)));
641 g
642 }
643
644 fn empty_layer(name: &str) -> StagedLayer {
645 staged_layer(name, StagedId::None, GeometryValues::default(), vec![])
646 }
647
648 fn staged_layer(
649 name: &str,
650 id: StagedId,
651 geometry: GeometryValues,
652 properties: Vec<StagedProperty>,
653 ) -> StagedLayer {
654 StagedLayer::new(name, 4096, id, geometry, properties).unwrap()
655 }
656
657 #[test]
658 fn prop_name_display_concatenates_parts() {
659 assert_eq!(PropName("addr:", "city").to_string(), "addr:city");
660 assert_eq!(PropName("name", "").to_string(), "name");
661 assert_eq!(PropName("", "").to_string(), "");
662 }
663
664 #[test]
665 fn prop_name_eq_str_matches_concatenation() {
666 assert_eq!(PropName("addr:", "city"), "addr:city");
667 assert_eq!("addr:city", PropName("addr:", "city"));
668 assert_ne!(PropName("addr:", "city"), "addr:");
669 assert_ne!(PropName("addr:", "city"), "city");
670 assert_eq!(PropName("name", ""), "name");
671 }
672
673 #[test]
674 fn prop_name_structural_eq_is_part_wise() {
675 assert_eq!(PropName("a", "b"), PropName("a", "b"));
676 assert_eq!(PropName("ab", ""), PropName("a", "b"));
677 }
678
679 #[test]
680 fn prop_name_eq_prop_name_semantic_equality() {
681 assert_eq!(PropName("ab", ""), PropName("a", "b"));
682 assert_eq!(PropName("", "ab"), PropName("a", "b"));
683 assert_eq!(PropName("abc", "def"), PropName("ab", "cdef"));
684 assert_eq!(PropName("a", "bcdef"), PropName("abcde", "f"));
685
686 assert_ne!(PropName("a", "b"), PropName("a", "c"));
687 assert_ne!(PropName("a", "b"), PropName("ab", "c"));
688 assert_ne!(PropName("abc", ""), PropName("ab", ""));
689 }
690
691 #[test]
692 fn prop_value_ref_scalars_convert_to_json() {
693 assert_eq!(Value::from(PropValueRef::Bool(true)), Value::Bool(true));
694 assert_eq!(Value::from(PropValueRef::Bool(false)), Value::Bool(false));
695 assert_eq!(Value::from(PropValueRef::I8(-1)), Value::from(-1_i8));
696 assert_eq!(Value::from(PropValueRef::U8(255)), Value::from(255_u8));
697 assert_eq!(
698 Value::from(PropValueRef::I32(-1000)),
699 Value::from(-1000_i32)
700 );
701 assert_eq!(Value::from(PropValueRef::U32(1000)), Value::from(1000_u32));
702 assert_eq!(
703 Value::from(PropValueRef::I64(i64::MIN)),
704 Value::from(i64::MIN)
705 );
706 assert_eq!(
707 Value::from(PropValueRef::U64(u64::MAX)),
708 Value::from(u64::MAX)
709 );
710 assert_eq!(
711 Value::from(PropValueRef::Str("hello")),
712 Value::String("hello".into())
713 );
714 }
715
716 #[test]
717 fn prop_value_ref_float_finite_is_number() {
718 assert!(matches!(
719 Value::from(PropValueRef::F32(1.5)),
720 Value::Number(_)
721 ));
722 assert!(matches!(
723 Value::from(PropValueRef::F64(2.5)),
724 Value::Number(_)
725 ));
726 }
727
728 #[test]
729 fn prop_value_ref_float_non_finite_becomes_string_sentinel() {
730 assert_eq!(
731 Value::from(PropValueRef::F32(f32::NAN)),
732 Value::String("f32::NAN".into())
733 );
734 assert_eq!(
735 Value::from(PropValueRef::F32(f32::INFINITY)),
736 Value::String("f32::INFINITY".into())
737 );
738 assert_eq!(
739 Value::from(PropValueRef::F64(f64::NAN)),
740 Value::String("f64::NAN".into())
741 );
742 assert_eq!(
743 Value::from(PropValueRef::F64(f64::NEG_INFINITY)),
744 Value::String("f64::NEG_INFINITY".into())
745 );
746 }
747
748 #[test]
749 fn empty_layer_yields_no_features() {
750 let buf = layer_buf(empty_layer("empty"));
751 let (_, layer) = Layer::from_bytes(&buf, &mut parser()).unwrap();
752 let Layer::Tag01(lazy) = layer else {
753 panic!("expected Tag01")
754 };
755 let parsed = lazy.decode_all(&mut dec()).unwrap();
756
757 let iter = parsed.iter_features();
758 assert_eq!(iter.len(), 0);
759 assert!(iter.is_empty());
760 assert_eq!(parsed.iter_features().len(), 0);
761 }
762
763 #[test]
764 fn len_decreases_with_each_next() {
765 let buf = layer_buf(staged_layer("test", StagedId::None, three_points(), vec![]));
766 let (_, layer) = Layer::from_bytes(&buf, &mut parser()).unwrap();
767 let Layer::Tag01(lazy) = layer else { panic!() };
768 let parsed = lazy.decode_all(&mut dec()).unwrap();
769
770 let mut iter = parsed.iter_features();
771 assert_eq!(iter.len(), 3);
772 iter.next().unwrap().unwrap();
773 assert_eq!(iter.len(), 2);
774 iter.next().unwrap().unwrap();
775 assert_eq!(iter.len(), 1);
776 iter.next().unwrap().unwrap();
777 assert_eq!(iter.len(), 0);
778 assert!(iter.is_empty());
779 assert!(iter.next().is_none());
780 }
781
782 #[test]
783 fn feature_ids_are_preserved() {
784 let buf = layer_buf(staged_layer(
785 "test",
786 StagedId::from_optional(vec![Some(100), None, Some(200)]),
787 three_points(),
788 vec![],
789 ));
790 let (_, layer) = Layer::from_bytes(&buf, &mut parser()).unwrap();
791 let Layer::Tag01(lazy) = layer else { panic!() };
792 let parsed = lazy.decode_all(&mut dec()).unwrap();
793
794 let mut ids = Vec::new();
795 let mut iter = parsed.iter_features();
796 while let Some(r) = iter.next() {
797 ids.push(r.unwrap().id);
798 }
799 assert_eq!(ids, [Some(100), None, Some(200)]);
800 }
801
802 #[test]
803 fn geometry_values_match_input() {
804 let buf = layer_buf(staged_layer("test", StagedId::None, three_points(), vec![]));
805 let (_, layer) = Layer::from_bytes(&buf, &mut parser()).unwrap();
806 let Layer::Tag01(lazy) = layer else { panic!() };
807 let parsed = lazy.decode_all(&mut dec()).unwrap();
808
809 let mut geoms = Vec::new();
810 let mut iter = parsed.iter_features();
811 while let Some(r) = iter.next() {
812 geoms.push(r.unwrap().geometry);
813 }
814 assert_eq!(geoms[0], Geometry::<i32>::Point(Point::new(1, 2)));
815 assert_eq!(geoms[1], Geometry::<i32>::Point(Point::new(3, 4)));
816 assert_eq!(geoms[2], Geometry::<i32>::Point(Point::new(5, 6)));
817 }
818
819 #[test]
820 fn null_scalar_values_are_skipped() {
821 let buf = layer_buf(staged_layer(
822 "test",
823 StagedId::None,
824 three_points(),
825 vec![StagedProperty::opt_u32("n", vec![Some(1), None, Some(3)])],
826 ));
827 let (_, layer) = Layer::from_bytes(&buf, &mut parser()).unwrap();
828 let Layer::Tag01(lazy) = layer else { panic!() };
829 let parsed = lazy.decode_all(&mut dec()).unwrap();
830
831 let mut iter = parsed.iter_features();
832
833 {
834 let feat = iter.next().unwrap().unwrap();
835 let cols: Vec<_> = feat.iter_properties().collect();
836 assert_eq!(cols.len(), 1);
837 assert_eq!(cols[0].name, PropName("n", ""));
838 assert_eq!(cols[0].name, "n");
839 assert_eq!(cols[0].value, PropValueRef::U32(1));
840 let all: Vec<_> = feat.iter_all_properties().collect();
841 assert_eq!(all, [Some(PropValueRef::U32(1))]);
842 }
843 {
844 let feat = iter.next().unwrap().unwrap();
845 assert!(feat.iter_properties().next().is_none());
846 let all: Vec<_> = feat.iter_all_properties().collect();
847 assert_eq!(all, [None]);
848 }
849 {
850 let feat = iter.next().unwrap().unwrap();
851 assert_eq!(feat.get_property("n"), Some(PropValueRef::U32(3)));
852 let all: Vec<_> = feat.iter_all_properties().collect();
853 assert_eq!(all, [Some(PropValueRef::U32(3))]);
854 }
855
856 let names: Vec<_> = parsed.iterate_prop_names().map(|n| n.to_string()).collect();
857 assert_eq!(names, ["n"]);
858 }
859
860 #[test]
861 fn null_string_values_are_skipped() {
862 let buf = layer_buf(staged_layer(
863 "test",
864 StagedId::None,
865 three_points(),
866 vec![StagedProperty::opt_str(
867 "label",
868 vec![Some("foo"), None, Some("bar")],
869 )],
870 ));
871 let (_, layer) = Layer::from_bytes(&buf, &mut parser()).unwrap();
872 let Layer::Tag01(lazy) = layer else { panic!() };
873 let parsed = lazy.decode_all(&mut dec()).unwrap();
874
875 let mut iter = parsed.iter_features();
876 {
877 let feat = iter.next().unwrap().unwrap();
878 assert_eq!(feat.get_property("label"), Some(PropValueRef::Str("foo")));
879 }
880 {
881 let feat = iter.next().unwrap().unwrap();
882 assert_eq!(feat.get_property("label"), None);
883 }
884 {
885 let feat = iter.next().unwrap().unwrap();
886 assert_eq!(feat.get_property("label"), Some(PropValueRef::Str("bar")));
887 }
888 }
889
890 #[test]
891 fn multiple_columns_independently_nullable() {
892 let buf = layer_buf(staged_layer(
893 "test",
894 StagedId::None,
895 three_points(),
896 vec![
897 StagedProperty::opt_bool("flag", vec![Some(true), Some(false), None]),
898 StagedProperty::opt_i32("score", vec![None, Some(-5), Some(7)]),
899 ],
900 ));
901 let (_, layer) = Layer::from_bytes(&buf, &mut parser()).unwrap();
902 let Layer::Tag01(lazy) = layer else { panic!() };
903 let parsed = lazy.decode_all(&mut dec()).unwrap();
904
905 let mut iter = parsed.iter_features();
906
907 {
909 let feat = iter.next().unwrap().unwrap();
910 assert_eq!(feat.iter_properties().count(), 1);
911 assert_eq!(feat.get_property("flag"), Some(PropValueRef::Bool(true)));
912 assert_eq!(feat.get_property("score"), None);
913 }
914 {
916 let feat = iter.next().unwrap().unwrap();
917 assert_eq!(feat.iter_properties().count(), 2);
918 assert_eq!(feat.get_property("flag"), Some(PropValueRef::Bool(false)));
919 assert_eq!(feat.get_property("score"), Some(PropValueRef::I32(-5)));
920 }
921 {
923 let feat = iter.next().unwrap().unwrap();
924 assert_eq!(feat.iter_properties().count(), 1);
925 assert_eq!(feat.get_property("flag"), None);
926 assert_eq!(feat.get_property("score"), Some(PropValueRef::I32(7)));
927 }
928 }
929
930 #[test]
931 fn geometry_error_does_not_misalign_ids() {
932 use crate::decoder::GeometryType;
933
934 let buf = layer_buf(staged_layer(
935 "test",
936 StagedId::from_optional(vec![Some(10), Some(20), Some(30)]),
937 three_points(),
938 vec![],
939 ));
940 let (_, layer) = Layer::from_bytes(&buf, &mut parser()).unwrap();
941 let Layer::Tag01(lazy) = layer else { panic!() };
942 let mut parsed = lazy.decode_all(&mut dec()).unwrap();
943
944 parsed.geometry.vector_types[1] = GeometryType::LineString;
948
949 let mut iter = parsed.iter_features();
950
951 let feat0 = iter.next().unwrap().unwrap();
953 assert_eq!(feat0.id, Some(10));
954
955 assert!(iter.next().unwrap().is_err());
957
958 let feat2 = iter.next().unwrap().unwrap();
960 assert_eq!(
961 feat2.id,
962 Some(30),
963 "id cursor was not advanced on geometry error"
964 );
965
966 assert!(iter.next().is_none());
967 }
968
969 #[test]
970 fn get_property_absent_column_returns_none() {
971 let buf = layer_buf(staged_layer(
972 "test",
973 StagedId::None,
974 three_points(),
975 vec![StagedProperty::u32("x", vec![1, 2, 3])],
976 ));
977 let (_, layer) = Layer::from_bytes(&buf, &mut parser()).unwrap();
978 let Layer::Tag01(lazy) = layer else { panic!() };
979 let parsed = lazy.decode_all(&mut dec()).unwrap();
980
981 let mut iter = parsed.iter_features();
982 let feat = iter.next().unwrap().unwrap();
983 assert_eq!(feat.get_property("no_such_column"), None);
984 }
985
986 #[test]
987 fn shared_dict_columns_are_expanded() {
988 let shared_dict = StagedSharedDict::new(
989 "addr:",
990 [
991 (
992 "city",
993 vec![Some("Paris"), Some("Rome"), None],
994 Presence::Mixed,
995 ),
996 (
997 "zip",
998 vec![Some("75001"), None, Some("00100")],
999 Presence::Mixed,
1000 ),
1001 ],
1002 )
1003 .unwrap();
1004
1005 let buf = layer_buf(staged_layer(
1006 "test",
1007 StagedId::None,
1008 three_points(),
1009 vec![StagedProperty::SharedDict(shared_dict)],
1010 ));
1011 let (_, layer) = Layer::from_bytes(&buf, &mut parser()).unwrap();
1012 let Layer::Tag01(lazy) = layer else { panic!() };
1013 let parsed = lazy.decode_all(&mut dec()).unwrap();
1014
1015 let mut iter = parsed.iter_features();
1016
1017 {
1019 let feat = iter.next().unwrap().unwrap();
1020 assert_eq!(
1021 feat.get_property("addr:city"),
1022 Some(PropValueRef::Str("Paris"))
1023 );
1024 assert_eq!(
1025 feat.get_property("addr:zip"),
1026 Some(PropValueRef::Str("75001"))
1027 );
1028 assert_eq!(feat.iter_properties().count(), 2);
1029 }
1030 {
1032 let feat = iter.next().unwrap().unwrap();
1033 assert_eq!(
1034 feat.get_property("addr:city"),
1035 Some(PropValueRef::Str("Rome"))
1036 );
1037 assert_eq!(feat.get_property("addr:zip"), None);
1038 assert_eq!(feat.iter_properties().count(), 1);
1039 let all: Vec<_> = feat.iter_all_properties().collect();
1041 assert_eq!(all, [Some(PropValueRef::Str("Rome")), None]);
1042 }
1043 {
1045 let feat = iter.next().unwrap().unwrap();
1046 assert_eq!(feat.get_property("addr:city"), None);
1047 assert_eq!(
1048 feat.get_property("addr:zip"),
1049 Some(PropValueRef::Str("00100"))
1050 );
1051 }
1052
1053 let names: Vec<_> = parsed.iterate_prop_names().map(|n| n.to_string()).collect();
1054 assert_eq!(names, ["addr:city", "addr:zip"]);
1055 }
1056
1057 fn strs<'p>(iter: impl Iterator<Item = PropName<'p>>) -> Vec<String> {
1058 iter.map(|n| n.to_string()).collect()
1059 }
1060
1061 fn reversed<'p>(iter: impl DoubleEndedIterator<Item = PropName<'p>>) -> Vec<String> {
1062 let mut names = strs(iter.rev());
1063 names.reverse();
1064 names
1065 }
1066
1067 fn both_ends_layer() -> Vec<u8> {
1068 let shared_dict = StagedSharedDict::new(
1069 "addr:",
1070 [
1071 ("city", vec![Some("Paris"); 3], Presence::AllPresent),
1072 ("zip", vec![Some("75001"); 3], Presence::AllPresent),
1073 ("street", vec![Some("Rue"); 3], Presence::AllPresent),
1074 ],
1075 )
1076 .unwrap();
1077
1078 layer_buf(staged_layer(
1079 "test",
1080 StagedId::None,
1081 three_points(),
1082 vec![
1083 StagedProperty::str("before", ["a", "a", "a"]),
1084 StagedProperty::u32("count", vec![1, 2, 3]),
1085 StagedProperty::SharedDict(shared_dict),
1086 StagedProperty::str("after", ["b", "b", "b"]),
1087 ],
1088 ))
1089 }
1090
1091 const BOTH_ENDS_NAMES: [&str; 6] = [
1092 "before",
1093 "count",
1094 "addr:city",
1095 "addr:zip",
1096 "addr:street",
1097 "after",
1098 ];
1099
1100 fn prop_names() -> Vec<PropName<'static>> {
1101 BOTH_ENDS_NAMES.iter().map(|n| PropName(n, "")).collect()
1102 }
1103
1104 #[test]
1105 fn prop_names_iterate_from_both_ends_lazy() {
1106 let buf = both_ends_layer();
1107 let (_, layer) = Layer::from_bytes(&buf, &mut parser()).unwrap();
1108 let Layer::Tag01(lazy) = layer else { panic!() };
1109
1110 assert_eq!(strs(lazy.iterate_prop_names()), BOTH_ENDS_NAMES);
1111 assert_eq!(reversed(lazy.iterate_prop_names()), BOTH_ENDS_NAMES);
1112 assert_size_hint_exact(|| lazy.iterate_prop_names(), &prop_names());
1113 }
1114
1115 #[test]
1116 fn prop_names_iterate_from_both_ends_parsed() {
1117 let buf = both_ends_layer();
1118 let (_, layer) = Layer::from_bytes(&buf, &mut parser()).unwrap();
1119 let Layer::Tag01(lazy) = layer else { panic!() };
1120 let parsed = lazy.decode_all(&mut dec()).unwrap();
1121
1122 assert_eq!(strs(parsed.iterate_prop_names()), BOTH_ENDS_NAMES);
1123 assert_eq!(reversed(parsed.iterate_prop_names()), BOTH_ENDS_NAMES);
1124
1125 assert_size_hint_exact(|| parsed.iterate_prop_names(), &prop_names());
1126 }
1127
1128 #[test]
1129 fn prop_names_of_layer_without_properties() {
1130 let buf = layer_buf(empty_layer("test"));
1131 let (_, layer) = Layer::from_bytes(&buf, &mut parser()).unwrap();
1132 let Layer::Tag01(lazy) = layer else { panic!() };
1133
1134 assert_eq!(lazy.iterate_prop_names().size_hint(), (0, Some(0)));
1135 assert_eq!(lazy.iterate_prop_names().next(), None);
1136 assert_eq!(lazy.iterate_prop_names().next_back(), None);
1137
1138 let parsed = lazy.decode_all(&mut dec()).unwrap();
1139 assert_eq!(parsed.iterate_prop_names().size_hint(), (0, Some(0)));
1140 assert_eq!(parsed.iterate_prop_names().next(), None);
1141 assert_eq!(parsed.iterate_prop_names().next_back(), None);
1142 }
1143
1144 #[test]
1147 fn prop_names_skip_columns_that_failed_to_parse() {
1148 let buf = both_ends_layer();
1149 let (_, layer) = Layer::from_bytes(&buf, &mut parser()).unwrap();
1150 let Layer::Tag01(lazy) = layer else { panic!() };
1151 let raw = lazy.properties.clone();
1152
1153 let (_, layer) = Layer::from_bytes(&buf, &mut parser()).unwrap();
1154 let Layer::Tag01(lazy) = layer else { panic!() };
1155 let parsed = lazy.decode_all(&mut dec()).unwrap().properties;
1156
1157 let mixed = vec![
1158 raw[0].clone(),
1159 LazyParsed::ParsingFailed,
1160 LazyParsed::Parsed(parsed[2].clone()),
1161 LazyParsed::ParsingFailed,
1162 raw[3].clone(),
1163 ];
1164 let expected = ["before", "addr:city", "addr:zip", "addr:street", "after"];
1165
1166 assert_eq!(strs(PropNamesIter::new(&mixed)), expected);
1167 assert_eq!(reversed(PropNamesIter::new(&mixed)), expected);
1168 assert_size_hint_exact(
1169 || PropNamesIter::new(&mixed),
1170 &expected.map(|n| PropName(n, "")),
1171 );
1172
1173 let all_failed = vec![LazyParsed::ParsingFailed; 3];
1174 assert_eq!(PropNamesIter::new(&all_failed).size_hint(), (0, Some(0)));
1175 assert_eq!(PropNamesIter::new(&all_failed).next(), None);
1176 assert_eq!(PropNamesIter::new(&all_failed).next_back(), None);
1177 }
1178
1179 #[test]
1180 fn feature_property_iterators_run_backwards() {
1181 let buf = both_ends_layer();
1182 let (_, layer) = Layer::from_bytes(&buf, &mut parser()).unwrap();
1183 let Layer::Tag01(lazy) = layer else { panic!() };
1184 let parsed = lazy.decode_all(&mut dec()).unwrap();
1185
1186 let mut iter = parsed.iter_features();
1187 let feat = iter.next().unwrap().unwrap();
1188
1189 let all: Vec<_> = feat.iter_all_properties().collect();
1190 assert_size_hint_exact(|| feat.iter_all_properties(), &all);
1191 let mut all_back: Vec<_> = feat.iter_all_properties().rev().collect();
1192 all_back.reverse();
1193 assert_eq!(all_back, all);
1194
1195 let mut props_back: Vec<_> = feat
1196 .iter_properties()
1197 .rev()
1198 .map(|c| c.name().to_string())
1199 .collect();
1200 props_back.reverse();
1201 assert_eq!(props_back, BOTH_ENDS_NAMES);
1202 }
1203}