1use crate::file::page_index::offset_index::PageLocation;
33use arrow_array::{Array, BooleanArray};
34use arrow_buffer::{BooleanBuffer, BooleanBufferBuilder};
35use arrow_select::filter::SlicesIterator;
36use std::cmp::Ordering;
37use std::collections::VecDeque;
38use std::ops::Range;
39
40mod algebra;
41mod boolean;
42mod cursor;
43mod ranges;
44mod selector;
45
46use algebra::{
47 and_then_mask, and_then_row_selections, and_then_selectors_with_mask, intersect_masks,
48 intersect_row_selections, union_masks, union_row_selections,
49};
50pub use boolean::MaskRunIter;
51use boolean::{
52 MaskSelection, limit_mask, mask_has_at_least_runs, offset_mask, split_off_mask, trim_mask,
53};
54pub(crate) use cursor::{LoadedRowRanges, MaskCursor, RowSelectionStrategy};
55pub use cursor::{RowSelectionCursor, RowSelectionPolicy};
56use ranges::{expand_to_batch_boundaries_from_selectors, scan_ranges_from_selectors};
57pub use selector::RowSelector;
58use selector::{limit_selectors, offset_selectors, split_off_selectors};
59
60#[derive(Default, Clone)]
118pub struct RowSelection {
119 inner: RowSelectionInner,
120}
121
122#[derive(Debug, Clone)]
124pub(crate) enum RowSelectionInner {
125 Selectors(Vec<RowSelector>),
126 Mask(Box<MaskSelection>),
127}
128
129impl Default for RowSelectionInner {
130 fn default() -> Self {
131 Self::Selectors(Vec::new())
132 }
133}
134
135impl std::fmt::Debug for RowSelection {
136 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
137 match &self.inner {
138 RowSelectionInner::Selectors(s) => f
139 .debug_struct("RowSelection")
140 .field("selectors", s)
141 .finish(),
142 RowSelectionInner::Mask(m) => f
143 .debug_struct("RowSelection")
144 .field("mask_len", &m.mask().len())
145 .finish_non_exhaustive(),
146 }
147 }
148}
149
150impl PartialEq for RowSelection {
151 fn eq(&self, other: &Self) -> bool {
152 match (&self.inner, &other.inner) {
153 (RowSelectionInner::Selectors(a), RowSelectionInner::Selectors(b)) => a == b,
154 (RowSelectionInner::Mask(a), RowSelectionInner::Mask(b)) => a.mask() == b.mask(),
155 (RowSelectionInner::Mask(mask), RowSelectionInner::Selectors(selectors))
156 | (RowSelectionInner::Selectors(selectors), RowSelectionInner::Mask(mask)) => {
157 if selectors
158 .iter()
159 .try_fold(0usize, |acc, selector| acc.checked_add(selector.row_count))
160 != Some(mask.mask().len())
161 {
162 return false;
163 }
164
165 let mut slices = mask.mask().set_slices().peekable();
166 let mut cursor = 0usize;
167
168 for selector in selectors {
169 let end = cursor + selector.row_count;
170
171 if selector.skip {
172 if slices.peek().is_some_and(|(start, _)| *start < end) {
173 return false;
174 }
175 } else {
176 match slices.next() {
177 Some((start, slice_end)) if start == cursor && slice_end == end => {}
178 _ => return false,
179 }
180 }
181
182 cursor = end;
183 }
184
185 slices.next().is_none()
186 }
187 }
188 }
189}
190
191impl Eq for RowSelection {}
192
193impl RowSelection {
194 fn from_selectors(selectors: Vec<RowSelector>) -> Self {
198 Self {
199 inner: RowSelectionInner::Selectors(selectors),
200 }
201 }
202
203 pub fn from_boolean_buffer(mask: BooleanBuffer) -> Self {
211 Self {
212 inner: RowSelectionInner::Mask(Box::new(MaskSelection::new(mask))),
213 }
214 }
215
216 fn from_mask_selection(mask: MaskSelection) -> Self {
217 Self {
218 inner: RowSelectionInner::Mask(Box::new(mask)),
219 }
220 }
221
222 pub fn as_mask(&self) -> Option<&BooleanBuffer> {
230 match &self.inner {
231 RowSelectionInner::Mask(m) => Some(m.mask()),
232 _ => None,
233 }
234 }
235
236 pub(crate) fn into_inner(self) -> RowSelectionInner {
238 self.inner
239 }
240
241 #[inline]
244 pub(crate) fn auto_selection_strategy(&self, threshold: usize) -> RowSelectionStrategy {
245 let (total_rows, effective_count) = match &self.inner {
246 RowSelectionInner::Selectors(selectors) => {
247 selectors.iter().fold((0usize, 0usize), |(rows, count), s| {
248 if s.row_count > 0 {
249 (rows + s.row_count, count + 1)
250 } else {
251 (rows, count)
252 }
253 })
254 }
255 RowSelectionInner::Mask(mask) => {
256 let mask = mask.mask();
257 let total_rows = mask.len();
258
259 if total_rows == 0 {
260 return RowSelectionStrategy::Mask;
261 }
262
263 let min_mask_runs = total_rows
271 .checked_div(threshold)
272 .and_then(|max_selector_runs| max_selector_runs.checked_add(1));
273
274 return match min_mask_runs {
275 Some(min_runs) if mask_has_at_least_runs(mask, min_runs) => {
276 RowSelectionStrategy::Mask
277 }
278 _ => RowSelectionStrategy::Selectors,
279 };
280 }
281 };
282
283 if effective_count == 0 {
284 return RowSelectionStrategy::Mask;
285 }
286
287 if total_rows < effective_count.saturating_mul(threshold) {
288 RowSelectionStrategy::Mask
289 } else {
290 RowSelectionStrategy::Selectors
291 }
292 }
293
294 #[cfg(test)]
295 fn selectors(&self) -> Vec<RowSelector> {
296 self.iter().copied().collect()
297 }
298
299 fn into_selectors_vec(self) -> Vec<RowSelector> {
300 match self.inner {
301 RowSelectionInner::Selectors(s) => s,
302 RowSelectionInner::Mask(m) => (*m).into_selectors(),
303 }
304 }
305
306 pub fn from_filters(filters: &[BooleanArray]) -> Self {
312 let mut next_offset = 0;
313 let total_rows = filters.iter().map(|x| x.len()).sum();
314
315 let iter = filters.iter().flat_map(|filter| {
316 let offset = next_offset;
317 next_offset += filter.len();
318 assert_eq!(filter.null_count(), 0);
319 SlicesIterator::new(filter).map(move |(start, end)| start + offset..end + offset)
320 });
321
322 Self::from_consecutive_ranges(iter, total_rows)
323 }
324
325 pub fn from_consecutive_ranges<I: Iterator<Item = Range<usize>>>(
327 ranges: I,
328 total_rows: usize,
329 ) -> Self {
330 let mut selectors: Vec<RowSelector> = Vec::with_capacity(ranges.size_hint().0);
331 let mut last_end = 0;
332 for range in ranges {
333 let len = range.end - range.start;
334 if len == 0 {
335 continue;
336 }
337
338 match range.start.cmp(&last_end) {
339 Ordering::Equal => match selectors.last_mut() {
340 Some(last) => last.row_count = last.row_count.checked_add(len).unwrap(),
341 None => selectors.push(RowSelector::select(len)),
342 },
343 Ordering::Greater => {
344 selectors.push(RowSelector::skip(range.start - last_end));
345 selectors.push(RowSelector::select(len))
346 }
347 Ordering::Less => panic!("out of order"),
348 }
349 last_end = range.end;
350 }
351
352 if last_end != total_rows {
353 selectors.push(RowSelector::skip(total_rows - last_end))
354 }
355
356 Self::from_selectors(selectors)
357 }
358
359 pub fn scan_ranges(&self, page_locations: &[PageLocation]) -> Vec<Range<u64>> {
369 match &self.inner {
370 RowSelectionInner::Selectors(selectors) => {
371 scan_ranges_from_selectors(selectors.iter().copied(), page_locations)
372 }
373 RowSelectionInner::Mask(mask) => {
374 scan_ranges_from_selectors(MaskRunIter::new(mask.mask()), page_locations)
375 }
376 }
377 }
378
379 pub(crate) fn row_ranges_for_selected_pages(
381 &self,
382 page_locations: &[PageLocation],
383 total_rows: usize,
384 ) -> Vec<Range<usize>> {
385 let mut selected_pages = self.scan_ranges(page_locations).into_iter().peekable();
386 let mut row_ranges = Vec::new();
387
388 for (idx, page) in page_locations.iter().enumerate() {
389 let Some(selected_page) = selected_pages.peek() else {
390 break;
391 };
392 if selected_page.start != page.offset as u64 {
393 continue;
394 }
395 selected_pages.next();
396
397 let end = page_locations
398 .get(idx + 1)
399 .map(|next| next.first_row_index as usize)
400 .unwrap_or(total_rows);
401 row_ranges.push(page.first_row_index as usize..end);
402 }
403
404 row_ranges
405 }
406
407 pub fn split_off(&mut self, row_count: usize) -> Self {
409 match std::mem::take(&mut self.inner) {
410 RowSelectionInner::Mask(mask) => {
411 let total = mask.cached_count();
412 let (head, tail) = split_off_mask((*mask).into_mask(), row_count);
413 let (head, tail) = match total {
416 Some(total) => {
417 let head_count = if tail.is_empty() {
418 total
419 } else {
420 head.count_set_bits()
421 };
422 (
423 MaskSelection::with_count(head, head_count),
424 MaskSelection::with_count(tail, total - head_count),
425 )
426 }
427 None => (MaskSelection::new(head), MaskSelection::new(tail)),
428 };
429 self.inner = RowSelectionInner::Mask(Box::new(tail));
430 Self::from_mask_selection(head)
431 }
432 RowSelectionInner::Selectors(selectors) => {
433 let (head, tail) = split_off_selectors(selectors, row_count);
434 self.inner = RowSelectionInner::Selectors(tail);
435 Self::from_selectors(head)
436 }
437 }
438 }
439
440 pub fn and_then(&self, other: &Self) -> Self {
463 match (&self.inner, &other.inner) {
464 (RowSelectionInner::Mask(mask), _) => {
465 Self::from_boolean_buffer(and_then_mask(mask.mask(), other))
466 }
467 (RowSelectionInner::Selectors(first), RowSelectionInner::Selectors(second)) => {
468 and_then_row_selections(first, second)
469 }
470 (RowSelectionInner::Selectors(first), RowSelectionInner::Mask(second)) => {
471 and_then_selectors_with_mask(first, second.mask())
472 }
473 }
474 }
475
476 pub fn intersection(&self, other: &Self) -> Self {
483 match (&self.inner, &other.inner) {
484 (RowSelectionInner::Mask(l), RowSelectionInner::Mask(r)) => {
485 Self::from_boolean_buffer(intersect_masks(l.mask(), r.mask()))
486 }
487 (RowSelectionInner::Selectors(l), RowSelectionInner::Selectors(r)) => {
488 intersect_row_selections(l, r)
489 }
490 (RowSelectionInner::Selectors(l), RowSelectionInner::Mask(r)) => {
491 intersect_row_selections(l, &r.borrowed_selectors())
492 }
493 (RowSelectionInner::Mask(l), RowSelectionInner::Selectors(r)) => {
494 intersect_row_selections(&l.borrowed_selectors(), r)
495 }
496 }
497 }
498
499 pub fn union(&self, other: &Self) -> Self {
506 match (&self.inner, &other.inner) {
507 (RowSelectionInner::Mask(l), RowSelectionInner::Mask(r)) => {
508 Self::from_boolean_buffer(union_masks(l.mask(), r.mask()))
509 }
510 (RowSelectionInner::Selectors(l), RowSelectionInner::Selectors(r)) => {
511 union_row_selections(l, r)
512 }
513 (RowSelectionInner::Selectors(l), RowSelectionInner::Mask(r)) => {
514 union_row_selections(l, &r.borrowed_selectors())
515 }
516 (RowSelectionInner::Mask(l), RowSelectionInner::Selectors(r)) => {
517 union_row_selections(&l.borrowed_selectors(), r)
518 }
519 }
520 }
521
522 pub fn selects_any(&self) -> bool {
524 match &self.inner {
525 RowSelectionInner::Selectors(s) => s.iter().any(|x| !x.skip),
526 RowSelectionInner::Mask(m) => match m.cached_count() {
527 Some(count) => count > 0,
528 None => m.mask().set_indices().next().is_some(),
529 },
530 }
531 }
532
533 pub(crate) fn trim(self) -> Self {
535 match self.inner {
536 RowSelectionInner::Mask(m) => {
537 let trimmed = trim_mask(m.mask());
538 let cached_count = m.cached_count();
539 match trimmed {
540 Some(mask) => match cached_count {
542 Some(count) => {
543 Self::from_mask_selection(MaskSelection::with_count(mask, count))
544 }
545 None => Self::from_boolean_buffer(mask),
546 },
547 None => Self {
549 inner: RowSelectionInner::Mask(m),
550 },
551 }
552 }
553 RowSelectionInner::Selectors(mut selectors) => {
554 while selectors.last().map(|x| x.skip).unwrap_or(false) {
555 selectors.pop();
556 }
557 Self::from_selectors(selectors)
558 }
559 }
560 }
561
562 pub(crate) fn offset(self, offset: usize) -> Self {
564 if offset == 0 {
565 return self;
566 }
567
568 match self.inner {
569 RowSelectionInner::Mask(mask) => {
570 let count = mask.count();
571 let buffer = offset_mask((*mask).into_mask(), offset, count);
572 Self::from_mask_selection(MaskSelection::with_count(
573 buffer,
574 count.saturating_sub(offset),
575 ))
576 }
577 RowSelectionInner::Selectors(selectors) => {
578 Self::from_selectors(offset_selectors(selectors, offset))
579 }
580 }
581 }
582
583 pub(crate) fn limit(self, limit: usize) -> Self {
585 match self.inner {
586 RowSelectionInner::Mask(mask) => {
587 let cached = mask.cached_count();
588 let buffer = limit_mask((*mask).into_mask(), limit);
589 match cached {
590 Some(count) => Self::from_mask_selection(MaskSelection::with_count(
591 buffer,
592 count.min(limit),
593 )),
594 None => Self::from_boolean_buffer(buffer),
595 }
596 }
597 RowSelectionInner::Selectors(selectors) => {
598 Self::from_selectors(limit_selectors(selectors, limit))
599 }
600 }
601 }
602
603 pub fn iter(&self) -> impl Iterator<Item = &RowSelector> {
613 match &self.inner {
614 RowSelectionInner::Selectors(s) => s.iter(),
615 RowSelectionInner::Mask(m) => m.selectors().iter(),
616 }
617 }
618
619 pub fn row_count(&self) -> usize {
621 match &self.inner {
622 RowSelectionInner::Selectors(s) => {
623 s.iter().filter(|x| !x.skip).map(|x| x.row_count).sum()
624 }
625 RowSelectionInner::Mask(m) => m.count(),
626 }
627 }
628
629 pub fn skipped_row_count(&self) -> usize {
631 match &self.inner {
632 RowSelectionInner::Selectors(s) => {
633 s.iter().filter(|x| x.skip).map(|x| x.row_count).sum()
634 }
635 RowSelectionInner::Mask(m) => m.mask().len() - m.count(),
636 }
637 }
638
639 pub(crate) fn expand_to_batch_boundaries(&self, batch_size: usize, total_rows: usize) -> Self {
643 if batch_size == 0 {
644 return self.clone();
645 }
646
647 match &self.inner {
648 RowSelectionInner::Selectors(selectors) => expand_to_batch_boundaries_from_selectors(
649 selectors.iter().copied(),
650 batch_size,
651 total_rows,
652 ),
653 RowSelectionInner::Mask(mask) => expand_to_batch_boundaries_from_selectors(
654 MaskRunIter::new(mask.mask()),
655 batch_size,
656 total_rows,
657 ),
658 }
659 }
660}
661
662impl From<Vec<RowSelector>> for RowSelection {
663 fn from(selectors: Vec<RowSelector>) -> Self {
664 selectors.into_iter().collect()
665 }
666}
667
668impl From<BooleanBuffer> for RowSelection {
669 fn from(mask: BooleanBuffer) -> Self {
670 Self::from_boolean_buffer(mask)
671 }
672}
673
674impl FromIterator<RowSelector> for RowSelection {
675 fn from_iter<T: IntoIterator<Item = RowSelector>>(iter: T) -> Self {
676 let iter = iter.into_iter();
677
678 let mut selectors = Vec::with_capacity(iter.size_hint().0);
680
681 let mut filtered = iter.filter(|x| x.row_count != 0);
682 if let Some(x) = filtered.next() {
683 selectors.push(x);
684 }
685
686 for s in filtered {
687 if s.row_count == 0 {
688 continue;
689 }
690
691 let last = selectors.last_mut().unwrap();
693 if last.skip == s.skip {
694 last.row_count = last.row_count.checked_add(s.row_count).unwrap();
695 } else {
696 selectors.push(s)
697 }
698 }
699
700 Self::from_selectors(selectors)
701 }
702}
703
704impl From<RowSelection> for Vec<RowSelector> {
705 fn from(r: RowSelection) -> Self {
706 r.into_selectors_vec()
707 }
708}
709
710impl From<RowSelection> for VecDeque<RowSelector> {
711 fn from(r: RowSelection) -> Self {
712 r.into_selectors_vec().into()
713 }
714}
715
716impl FromIterator<RowSelection> for RowSelection {
717 fn from_iter<T: IntoIterator<Item = RowSelection>>(iter: T) -> Self {
723 let items: Vec<RowSelection> = iter.into_iter().collect();
724
725 let all_mask = items
726 .iter()
727 .all(|s| matches!(&s.inner, RowSelectionInner::Mask(_)));
728
729 if all_mask {
730 let total_len: usize = items
731 .iter()
732 .map(|s| match &s.inner {
733 RowSelectionInner::Mask(m) => m.mask().len(),
734 RowSelectionInner::Selectors(_) => unreachable!(),
735 })
736 .sum();
737 let mut builder = BooleanBufferBuilder::new(total_len);
738 for item in items {
739 match item.into_inner() {
740 RowSelectionInner::Mask(m) => builder.append_buffer(m.mask()),
741 RowSelectionInner::Selectors(_) => unreachable!(),
742 }
743 }
744 return Self::from_boolean_buffer(builder.finish());
745 }
746
747 items
748 .into_iter()
749 .flat_map(|s| s.into_selectors_vec())
750 .collect()
751 }
752}
753
754#[cfg(test)]
755mod tests {
756 use super::*;
757
758 #[test]
759 fn test_offset_zero_and_zero_batch_expand_are_identity() {
760 let selection =
761 RowSelection::from_boolean_buffer(BooleanBuffer::from(vec![true, false, true]));
762 assert_eq!(selection.clone().offset(0), selection);
763 assert_eq!(selection.expand_to_batch_boundaries(0, 3), selection);
764 }
765
766 #[test]
767 fn test_from_filters() {
768 let filters = vec![
769 BooleanArray::from(vec![false, false, false, true, true, true, true]),
770 BooleanArray::from(vec![true, true, false, false, true, true, true]),
771 BooleanArray::from(vec![false, false, false, false]),
772 BooleanArray::from(Vec::<bool>::new()),
773 ];
774
775 let selection = RowSelection::from_filters(&filters[..1]);
776 assert!(selection.selects_any());
777 assert_eq!(
778 selection.selectors(),
779 vec![RowSelector::skip(3), RowSelector::select(4)]
780 );
781
782 let selection = RowSelection::from_filters(&filters[..2]);
783 assert!(selection.selects_any());
784 assert_eq!(
785 selection.selectors(),
786 vec![
787 RowSelector::skip(3),
788 RowSelector::select(6),
789 RowSelector::skip(2),
790 RowSelector::select(3)
791 ]
792 );
793
794 let selection = RowSelection::from_filters(&filters);
795 assert!(selection.selects_any());
796 assert_eq!(
797 selection.selectors(),
798 vec![
799 RowSelector::skip(3),
800 RowSelector::select(6),
801 RowSelector::skip(2),
802 RowSelector::select(3),
803 RowSelector::skip(4)
804 ]
805 );
806
807 let selection = RowSelection::from_filters(&filters[2..3]);
808 assert!(!selection.selects_any());
809 assert_eq!(selection.selectors(), vec![RowSelector::skip(4)]);
810 }
811
812 #[test]
813 fn test_iter() {
814 let selectors = vec![
817 RowSelector::select(3),
818 RowSelector::skip(33),
819 RowSelector::select(4),
820 ];
821
822 let round_tripped: Vec<RowSelector> = RowSelection::from(selectors.clone())
823 .iter()
824 .copied()
825 .collect();
826 assert_eq!(selectors, round_tripped);
827 }
828
829 #[test]
830 fn test_row_count() {
831 let selection = RowSelection::from(vec![
832 RowSelector::skip(34),
833 RowSelector::select(12),
834 RowSelector::skip(3),
835 RowSelector::select(35),
836 ]);
837
838 assert_eq!(selection.row_count(), 12 + 35);
839 assert_eq!(selection.skipped_row_count(), 34 + 3);
840
841 let selection = RowSelection::from(vec![RowSelector::select(12), RowSelector::select(35)]);
842
843 assert_eq!(selection.row_count(), 12 + 35);
844 assert_eq!(selection.skipped_row_count(), 0);
845
846 let selection = RowSelection::from(vec![RowSelector::skip(34), RowSelector::skip(3)]);
847
848 assert_eq!(selection.row_count(), 0);
849 assert_eq!(selection.skipped_row_count(), 34 + 3);
850
851 let selection = RowSelection::from(vec![]);
852
853 assert_eq!(selection.row_count(), 0);
854 assert_eq!(selection.skipped_row_count(), 0);
855 }
856
857 #[test]
858 fn test_mixed_backing_equality_mismatches() {
859 let mask =
860 RowSelection::from_boolean_buffer(BooleanBuffer::from(vec![true, false, true, true]));
861
862 let longer = RowSelection::from(vec![
864 RowSelector::select(1),
865 RowSelector::skip(1),
866 RowSelector::select(2),
867 RowSelector::skip(1),
868 ]);
869 assert_ne!(mask, longer);
870 assert_ne!(longer, mask);
871
872 let skip_overlap = RowSelection::from(vec![RowSelector::skip(2), RowSelector::select(2)]);
874 assert_ne!(mask, skip_overlap);
875
876 let misaligned = RowSelection::from(vec![
878 RowSelector::select(2),
879 RowSelector::skip(1),
880 RowSelector::select(1),
881 ]);
882 assert_ne!(mask, misaligned);
883
884 let equal = RowSelection::from(vec![
885 RowSelector::select(1),
886 RowSelector::skip(1),
887 RowSelector::select(2),
888 ]);
889 assert_eq!(mask, equal);
890 assert_eq!(equal, mask);
891 }
892
893 #[test]
894 fn test_from_iter_all_mask_preserves_mask_backing() {
895 let a_bits = vec![true, false, true, true];
896 let b_bits = vec![false, true, false];
897 let c_bits = vec![true, true, false, false, true];
898
899 let parts = vec![
900 RowSelection::from_boolean_buffer(BooleanBuffer::from(a_bits.clone())),
901 RowSelection::from_boolean_buffer(BooleanBuffer::from(b_bits.clone())),
902 RowSelection::from_boolean_buffer(BooleanBuffer::from(c_bits.clone())),
903 ];
904 let collected: RowSelection = parts.into_iter().collect();
905
906 let combined = a_bits
907 .iter()
908 .chain(b_bits.iter())
909 .chain(c_bits.iter())
910 .copied()
911 .collect::<Vec<_>>();
912 let expected = RowSelection::from_filters(&[BooleanArray::from(combined)]);
913
914 assert!(collected.as_mask().is_some());
915 assert_eq!(collected, expected);
916 }
917
918 #[test]
919 fn test_from_iter_mixed_backing_falls_back_to_selectors() {
920 let a_bits = vec![true, false, true];
921 let b_selectors = vec![RowSelector::skip(2), RowSelector::select(3)];
922 let c_bits = vec![false, true];
923
924 let parts = vec![
925 RowSelection::from_boolean_buffer(BooleanBuffer::from(a_bits.clone())),
926 RowSelection::from(b_selectors),
927 RowSelection::from_boolean_buffer(BooleanBuffer::from(c_bits.clone())),
928 ];
929 let collected: RowSelection = parts.into_iter().collect();
930
931 assert!(collected.as_mask().is_none());
932
933 let combined_bits = vec![
934 true, false, true, false, false, true, true, true, false, true,
935 ];
936 let expected = RowSelection::from_filters(&[BooleanArray::from(combined_bits)]);
937 assert_eq!(collected, expected);
938 }
939
940 #[test]
941 fn test_from_iter_empty_yields_empty_selection() {
942 let collected: RowSelection = std::iter::empty::<RowSelection>().collect();
943 assert_eq!(collected, RowSelection::default());
944 assert!(collected.as_mask().is_some());
945 assert_eq!(collected.as_mask().unwrap().len(), 0);
946 }
947}