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