Skip to main content

lance_table/rowids/
segment.rs

1// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright The Lance Authors
3
4use std::ops::{Range, RangeInclusive};
5
6use super::{bitmap::Bitmap, encoded_array::EncodedU64Array};
7use lance_core::deepsize::DeepSizeOf;
8
9/// Convert an estimated serialized byte cost from `u128` to `usize`, saturating
10/// at [`usize::MAX`] when the value does not fit (infeasible encodings).
11#[inline]
12fn u128_byte_cost_to_usize(v: u128) -> usize {
13    usize::try_from(v).unwrap_or(usize::MAX)
14}
15
16/// Different ways to represent a sequence of distinct u64s.
17///
18/// This is designed to be especially efficient for sequences that are sorted,
19/// but not meaningfully larger than a `Vec<u64>` in the worst case.
20///
21/// The representation is chosen based on the properties of the sequence:
22///                                                           
23///  Sorted?───►Yes ───►Contiguous?─► Yes─► Range            
24///    │                ▼                                 
25///    │                No                                
26///    │                ▼                                 
27///    │              Dense?─────► Yes─► RangeWithBitmap/RangeWithHoles
28///    │                ▼                                 
29///    │                No─────────────► SortedArray      
30///    ▼                                                    
31///    No──────────────────────────────► Array            
32///
33/// "Dense" is decided based on the estimated byte size of the representation.
34///
35/// Size of RangeWithBitMap for N values:
36///     8 bytes + 8 bytes + ceil((max - min) / 8) bytes
37/// Size of SortedArray for N values (assuming u16 packed):
38///     8 bytes + 8 bytes + 8 bytes + 2 bytes * N
39///
40#[derive(Debug, PartialEq, Eq, Clone)]
41pub enum U64Segment {
42    /// A contiguous sorted range of row ids.
43    ///
44    /// Total size: 16 bytes
45    Range(Range<u64>),
46    /// A sorted range of row ids, that is mostly contiguous.
47    ///
48    /// Total size: 24 bytes + n_holes * 4 bytes
49    /// Use when: 32 * n_holes < max - min
50    RangeWithHoles {
51        range: Range<u64>,
52        /// Bitmap of offsets from the start of the range that are holes.
53        /// This is sorted, so binary search can be used. It's typically
54        /// relatively small.
55        holes: EncodedU64Array,
56    },
57    /// A sorted range of row ids, that is mostly contiguous.
58    ///
59    /// Bitmap is 1 when the value is present, 0 when it's missing.
60    ///
61    /// Total size: 24 bytes + ceil((max - min) / 8) bytes
62    /// Use when: max - min > 16 * len
63    RangeWithBitmap { range: Range<u64>, bitmap: Bitmap },
64    /// A sorted array of row ids, that is sparse.
65    ///
66    /// Total size: 24 bytes + 2 * n_values bytes
67    SortedArray(EncodedU64Array),
68    /// An array of row ids, that is not sorted.
69    Array(EncodedU64Array),
70}
71
72impl DeepSizeOf for U64Segment {
73    fn deep_size_of_children(&self, context: &mut lance_core::deepsize::Context) -> usize {
74        match self {
75            Self::Range(_) => 0,
76            Self::RangeWithHoles { holes, .. } => holes.deep_size_of_children(context),
77            Self::RangeWithBitmap { bitmap, .. } => bitmap.deep_size_of_children(context),
78            Self::SortedArray(array) => array.deep_size_of_children(context),
79            Self::Array(array) => array.deep_size_of_children(context),
80        }
81    }
82}
83
84/// Statistics about a segment of u64s.
85#[derive(Debug)]
86struct SegmentStats {
87    /// Min value in the segment.
88    min: u64,
89    /// Max value in the segment
90    max: u64,
91    /// Total number of values in the segment
92    count: u64,
93    /// Whether the segment is sorted
94    sorted: bool,
95}
96
97impl SegmentStats {
98    /// Number of missing values ("holes") in the range `[min, max]`.
99    ///
100    /// Returns `u128` because the total slot count `max - min + 1` can be up
101    /// to `2^64` (when `min = 0, max = u64::MAX`), which exceeds `u64::MAX`.
102    fn n_holes(&self) -> u128 {
103        debug_assert!(self.sorted);
104        if self.count == 0 {
105            0
106        } else {
107            let total_slots = self.max as u128 - self.min as u128 + 1;
108            total_slots - self.count as u128
109        }
110    }
111}
112
113impl U64Segment {
114    /// Return the values that are missing from the slice.
115    fn holes_in_slice<'a>(
116        range: RangeInclusive<u64>,
117        existing: impl IntoIterator<Item = u64> + 'a,
118    ) -> impl Iterator<Item = u64> + 'a {
119        let mut existing = existing.into_iter().peekable();
120        range.filter(move |val| {
121            if let Some(&existing_val) = existing.peek()
122                && existing_val == *val
123            {
124                existing.next();
125                return false;
126            }
127            true
128        })
129    }
130
131    fn compute_stats(values: impl IntoIterator<Item = u64>) -> SegmentStats {
132        let mut sorted = true;
133        let mut min = u64::MAX;
134        let mut max = 0;
135        let mut count = 0;
136
137        for val in values {
138            count += 1;
139            if val < min {
140                min = val;
141            }
142            if val > max {
143                max = val;
144            }
145            if sorted && count > 1 && val < max {
146                sorted = false;
147            }
148        }
149
150        if count == 0 {
151            min = 0;
152            max = 0;
153        }
154
155        SegmentStats {
156            min,
157            max,
158            count,
159            sorted,
160        }
161    }
162
163    /// Estimate the serialized byte size of each sorted encoding variant.
164    ///
165    /// All arithmetic is performed in `u128` to avoid overflow when the range
166    /// span `max - min + 1` approaches or exceeds `2^64`. Infeasible sizes
167    /// saturate to `usize::MAX` so they always lose the `min()` comparison.
168    fn sorted_sequence_sizes(stats: &SegmentStats) -> [usize; 3] {
169        let n_holes = stats.n_holes();
170        let total_slots = stats.max as u128 - stats.min as u128 + 1;
171
172        let range_with_holes = 24u128.saturating_add(4u128.saturating_mul(n_holes));
173        let range_with_bitmap = 24u128.saturating_add(total_slots.div_ceil(8));
174        let sorted_array = 24u128.saturating_add(2u128.saturating_mul(stats.count as u128));
175
176        [
177            u128_byte_cost_to_usize(range_with_holes),
178            u128_byte_cost_to_usize(range_with_bitmap),
179            u128_byte_cost_to_usize(sorted_array),
180        ]
181    }
182
183    fn from_stats_and_sequence(
184        stats: SegmentStats,
185        sequence: impl IntoIterator<Item = u64>,
186    ) -> Self {
187        if stats.sorted {
188            let n_holes = stats.n_holes();
189            // Range-backed encodings store an exclusive end as `Range<u64>`,
190            // which cannot represent `u64::MAX + 1`. Compute the end once and
191            // gate all range-backed branches on its representability.
192            let exclusive_end = stats.max.checked_add(1);
193            if stats.count == 0 {
194                Self::Range(0..0)
195            } else if n_holes == 0 && exclusive_end.is_some() {
196                Self::Range(stats.min..exclusive_end.unwrap())
197            } else if let Some(end) = exclusive_end {
198                let sizes = Self::sorted_sequence_sizes(&stats);
199                let min_size = sizes.iter().min().unwrap();
200                if min_size == &sizes[0] {
201                    let range = stats.min..end;
202                    let mut holes =
203                        Self::holes_in_slice(stats.min..=stats.max, sequence).collect::<Vec<_>>();
204                    holes.sort_unstable();
205                    let holes = EncodedU64Array::from(holes);
206                    Self::RangeWithHoles { range, holes }
207                } else if min_size == &sizes[1] {
208                    let range = stats.min..end;
209                    let mut bitmap = Bitmap::new_full((stats.max - stats.min) as usize + 1);
210                    for hole in Self::holes_in_slice(stats.min..=stats.max, sequence) {
211                        let offset = (hole - stats.min) as usize;
212                        bitmap.clear(offset);
213                    }
214                    Self::RangeWithBitmap { range, bitmap }
215                } else {
216                    Self::SortedArray(EncodedU64Array::from_iter(sequence))
217                }
218            } else {
219                // max == u64::MAX: exclusive end is unrepresentable in Range<u64>,
220                // so no range-backed encoding can be used.
221                Self::SortedArray(EncodedU64Array::from_iter(sequence))
222            }
223        } else {
224            Self::Array(EncodedU64Array::from_iter(sequence))
225        }
226    }
227
228    pub fn from_slice(slice: &[u64]) -> Self {
229        Self::from_iter(slice.iter().copied())
230    }
231}
232
233impl FromIterator<u64> for U64Segment {
234    fn from_iter<T: IntoIterator<Item = u64>>(iter: T) -> Self {
235        let values: Vec<u64> = iter.into_iter().collect();
236        let stats = Self::compute_stats(values.iter().copied());
237        Self::from_stats_and_sequence(stats, values)
238    }
239}
240
241impl U64Segment {
242    pub fn iter(&self) -> Box<dyn DoubleEndedIterator<Item = u64> + '_> {
243        match self {
244            Self::Range(range) => Box::new(range.clone()),
245            Self::RangeWithHoles { range, holes } => {
246                Box::new((range.start..range.end).filter(move |&val| {
247                    // TODO: we could write a more optimal version of this
248                    // iterator, but would need special handling to make it
249                    // double ended.
250                    holes.binary_search(val).is_err()
251                }))
252            }
253            Self::RangeWithBitmap { range, bitmap } => {
254                Box::new((range.start..range.end).filter(|val| {
255                    let offset = (val - range.start) as usize;
256                    bitmap.get(offset)
257                }))
258            }
259            Self::SortedArray(array) => Box::new(array.iter()),
260            Self::Array(array) => Box::new(array.iter()),
261        }
262    }
263
264    pub fn len(&self) -> usize {
265        match self {
266            Self::Range(range) => (range.end - range.start) as usize,
267            Self::RangeWithHoles { range, holes } => {
268                let holes = holes.iter().count();
269                (range.end - range.start) as usize - holes
270            }
271            Self::RangeWithBitmap { range, bitmap } => {
272                let holes = bitmap.count_zeros();
273                (range.end - range.start) as usize - holes
274            }
275            Self::SortedArray(array) => array.len(),
276            Self::Array(array) => array.len(),
277        }
278    }
279
280    pub(crate) fn use_dense_range_expansion(&self, segment_len: usize) -> bool {
281        let Self::RangeWithBitmap { bitmap, .. } = self else {
282            return false;
283        };
284        // Keep sparse segments on the compact per-bit decoder. Contiguous-run
285        // expansion pays off when dense bytes dominate the segment.
286        let dense_threshold = bitmap.len().saturating_sub(bitmap.len() / 4);
287        segment_len >= dense_threshold
288    }
289
290    pub fn is_empty(&self) -> bool {
291        self.len() == 0
292    }
293
294    /// Get the min and max value of the segment, excluding tombstones.
295    ///
296    /// Returns `None` for an empty segment, which has no extrema. Decoding accepts an
297    /// empty encoding of every variant, so no arm here may assume it holds a value.
298    pub fn range(&self) -> Option<RangeInclusive<u64>> {
299        match self {
300            Self::Range(range)
301            | Self::RangeWithBitmap { range, .. }
302            | Self::RangeWithHoles { range, .. } => {
303                (!range.is_empty()).then(|| range.start..=(range.end - 1))
304            }
305            // We can assume that the array is sorted.
306            Self::SortedArray(array) => Some(array.first()?..=array.last()?),
307            Self::Array(array) => Some(array.min()?..=array.max()?),
308        }
309    }
310
311    pub fn slice(&self, offset: usize, len: usize) -> Self {
312        if len == 0 {
313            return Self::Range(0..0);
314        }
315
316        let values: Vec<u64> = self.iter().skip(offset).take(len).collect();
317
318        // `from_slice` will compute stats and select the best representation.
319        Self::from_slice(&values)
320    }
321
322    pub fn position(&self, val: u64) -> Option<usize> {
323        match self {
324            Self::Range(range) => {
325                if range.contains(&val) {
326                    Some((val - range.start) as usize)
327                } else {
328                    None
329                }
330            }
331            Self::RangeWithHoles { range, holes } => {
332                if !range.contains(&val) {
333                    return None;
334                }
335                // binary_search returns Err(idx) where idx is the count of holes
336                // strictly less than val (holes are unique and sorted).
337                match holes.binary_search(val) {
338                    Ok(_) => None,
339                    Err(num_holes_before) => {
340                        let offset = (val - range.start) as usize;
341                        Some(offset - num_holes_before)
342                    }
343                }
344            }
345            Self::RangeWithBitmap { range, bitmap } => {
346                if range.contains(&val) && bitmap.get((val - range.start) as usize) {
347                    let offset = (val - range.start) as usize;
348                    let num_zeros = bitmap.slice(0, offset).count_zeros();
349                    Some(offset - num_zeros)
350                } else {
351                    None
352                }
353            }
354            Self::SortedArray(array) => array.binary_search(val).ok(),
355            Self::Array(array) => array.iter().position(|v| v == val),
356        }
357    }
358
359    pub fn get(&self, i: usize) -> Option<u64> {
360        match self {
361            Self::Range(range) => match range.start.checked_add(i as u64) {
362                Some(val) if val < range.end => Some(val),
363                _ => None,
364            },
365            Self::RangeWithHoles { range, holes } => {
366                let len = (range.end - range.start) as usize - holes.len();
367                if i >= len {
368                    return None;
369                }
370                // The i-th surviving value v satisfies v = range.start + i + k,
371                // where k = |{h ∈ holes : h < v}|. holes[k] - k is monotone
372                // non-decreasing in k (holes are sorted and unique), so binary
373                // search for the smallest k such that holes[k] - k > range.start + i.
374                let target = range.start + i as u64;
375                let mut lo = 0usize;
376                let mut hi = holes.len();
377                while lo < hi {
378                    let mid = (lo + hi) / 2;
379                    let h = holes.get(mid).unwrap();
380                    if h.saturating_sub(mid as u64) > target {
381                        hi = mid;
382                    } else {
383                        lo = mid + 1;
384                    }
385                }
386                Some(range.start + i as u64 + lo as u64)
387            }
388            Self::RangeWithBitmap { .. } => self.cursor().get(i),
389            Self::SortedArray(array) => array.get(i),
390            Self::Array(array) => array.get(i),
391        }
392    }
393
394    /// Reads values at non-decreasing indices in one pass.
395    pub fn cursor(&self) -> SegmentCursor<'_> {
396        SegmentCursor {
397            segment: self,
398            state: SegmentCursorState::default(),
399        }
400    }
401
402    /// Check if a value is contained in the segment
403    pub fn contains(&self, val: u64) -> bool {
404        match self {
405            Self::Range(range) => range.contains(&val),
406            Self::RangeWithHoles { range, holes } => {
407                if !range.contains(&val) {
408                    return false;
409                }
410                // Check if the value is not in the holes
411                !holes.iter().any(|hole| hole == val)
412            }
413            Self::RangeWithBitmap { range, bitmap } => {
414                if !range.contains(&val) {
415                    return false;
416                }
417                // Check if the bitmap has the value set (not cleared)
418                let idx = (val - range.start) as usize;
419                bitmap.get(idx)
420            }
421            Self::SortedArray(array) => array.binary_search(val).is_ok(),
422            Self::Array(array) => array.iter().any(|v| v == val),
423        }
424    }
425
426    /// Produce a new segment that has `val` as the new highest value in the segment
427    pub fn with_new_high(self, val: u64) -> lance_core::Result<Self> {
428        // Check that the new value is higher than the current maximum
429        if let Some(range) = self.range()
430            && val <= *range.end()
431        {
432            return Err(lance_core::Error::invalid_input(format!(
433                "New value {} must be higher than current maximum {}",
434                val,
435                range.end()
436            )));
437        }
438
439        Ok(match self {
440            Self::Range(range) => {
441                // Special case for empty range: create a range containing only the new value
442                if range.start == range.end {
443                    Self::Range(Range {
444                        start: val,
445                        end: val + 1,
446                    })
447                } else if val == range.end {
448                    Self::Range(Range {
449                        start: range.start,
450                        end: val + 1,
451                    })
452                } else {
453                    Self::RangeWithHoles {
454                        range: Range {
455                            start: range.start,
456                            end: val + 1,
457                        },
458                        holes: EncodedU64Array::U64((range.end..val).collect()),
459                    }
460                }
461            }
462            Self::RangeWithHoles { range, holes } => {
463                if val == range.end {
464                    Self::RangeWithHoles {
465                        range: Range {
466                            start: range.start,
467                            end: val + 1,
468                        },
469                        holes,
470                    }
471                } else {
472                    let mut new_holes: Vec<u64> = holes.iter().collect();
473                    new_holes.extend(range.end..val);
474                    Self::RangeWithHoles {
475                        range: Range {
476                            start: range.start,
477                            end: val + 1,
478                        },
479                        holes: EncodedU64Array::U64(new_holes),
480                    }
481                }
482            }
483            Self::RangeWithBitmap { range, bitmap } => {
484                let new_range = Range {
485                    start: range.start,
486                    end: val + 1,
487                };
488                let gap_size = (val - range.end) as usize;
489                let new_bitmap = bitmap
490                    .iter()
491                    .chain(std::iter::repeat_n(false, gap_size))
492                    .chain(std::iter::once(true))
493                    .collect::<Vec<bool>>();
494
495                Self::RangeWithBitmap {
496                    range: new_range,
497                    bitmap: Bitmap::from(new_bitmap.as_slice()),
498                }
499            }
500            Self::SortedArray(array) => match array {
501                EncodedU64Array::U64(mut vec) => {
502                    vec.push(val);
503                    Self::SortedArray(EncodedU64Array::U64(vec))
504                }
505                EncodedU64Array::U16 { base, offsets } => {
506                    if let Some(offset) = val.checked_sub(base) {
507                        if offset <= u16::MAX as u64 {
508                            let mut offsets = offsets;
509                            offsets.push(offset as u16);
510                            return Ok(Self::SortedArray(EncodedU64Array::U16 { base, offsets }));
511                        } else if offset <= u32::MAX as u64 {
512                            let mut u32_offsets: Vec<u32> =
513                                offsets.into_iter().map(|o| o as u32).collect();
514                            u32_offsets.push(offset as u32);
515                            return Ok(Self::SortedArray(EncodedU64Array::U32 {
516                                base,
517                                offsets: u32_offsets,
518                            }));
519                        }
520                    }
521                    let mut new_array: Vec<u64> =
522                        offsets.into_iter().map(|o| base + o as u64).collect();
523                    new_array.push(val);
524                    Self::SortedArray(EncodedU64Array::from(new_array))
525                }
526                EncodedU64Array::U32 { base, mut offsets } => {
527                    if let Some(offset) = val.checked_sub(base)
528                        && offset <= u32::MAX as u64
529                    {
530                        offsets.push(offset as u32);
531                        return Ok(Self::SortedArray(EncodedU64Array::U32 { base, offsets }));
532                    }
533                    let mut new_array: Vec<u64> =
534                        offsets.into_iter().map(|o| base + o as u64).collect();
535                    new_array.push(val);
536                    Self::SortedArray(EncodedU64Array::from(new_array))
537                }
538            },
539            Self::Array(array) => match array {
540                EncodedU64Array::U64(mut vec) => {
541                    vec.push(val);
542                    Self::Array(EncodedU64Array::U64(vec))
543                }
544                EncodedU64Array::U16 { base, offsets } => {
545                    if let Some(offset) = val.checked_sub(base) {
546                        if offset <= u16::MAX as u64 {
547                            let mut offsets = offsets;
548                            offsets.push(offset as u16);
549                            return Ok(Self::Array(EncodedU64Array::U16 { base, offsets }));
550                        } else if offset <= u32::MAX as u64 {
551                            let mut u32_offsets: Vec<u32> =
552                                offsets.into_iter().map(|o| o as u32).collect();
553                            u32_offsets.push(offset as u32);
554                            return Ok(Self::Array(EncodedU64Array::U32 {
555                                base,
556                                offsets: u32_offsets,
557                            }));
558                        }
559                    }
560                    let mut new_array: Vec<u64> =
561                        offsets.into_iter().map(|o| base + o as u64).collect();
562                    new_array.push(val);
563                    Self::Array(EncodedU64Array::from(new_array))
564                }
565                EncodedU64Array::U32 { base, mut offsets } => {
566                    if let Some(offset) = val.checked_sub(base)
567                        && offset <= u32::MAX as u64
568                    {
569                        offsets.push(offset as u32);
570                        return Ok(Self::Array(EncodedU64Array::U32 { base, offsets }));
571                    }
572                    let mut new_array: Vec<u64> =
573                        offsets.into_iter().map(|o| base + o as u64).collect();
574                    new_array.push(val);
575                    Self::Array(EncodedU64Array::from(new_array))
576                }
577            },
578        })
579    }
580
581    /// Delete a set of row ids from the segment.
582    /// The row ids are assumed to be in the segment. (within the range, not
583    /// already deleted.)
584    /// They are also assumed to be ordered by appearance in the segment.
585    pub fn delete(&self, vals: &[u64]) -> Self {
586        // TODO: can we enforce these assumptions? or make them safer?
587        debug_assert!(vals.iter().all(|&val| self.range().unwrap().contains(&val)));
588
589        let make_new_iter = || {
590            let mut vals_iter = vals.iter().copied().peekable();
591            self.iter().filter(move |val| {
592                if let Some(&next_val) = vals_iter.peek()
593                    && next_val == *val
594                {
595                    vals_iter.next();
596                    return false;
597                }
598                true
599            })
600        };
601        let stats = Self::compute_stats(make_new_iter());
602        Self::from_stats_and_sequence(stats, make_new_iter())
603    }
604
605    pub fn mask(&mut self, positions: &[u32]) {
606        if positions.is_empty() {
607            return;
608        }
609        if positions.len() == self.len() {
610            *self = Self::Range(0..0);
611            return;
612        }
613        let count = (self.len() - positions.len()) as u64;
614        let sorted = match self {
615            Self::Range(_) => true,
616            Self::RangeWithHoles { .. } => true,
617            Self::RangeWithBitmap { .. } => true,
618            Self::SortedArray(_) => true,
619            Self::Array(_) => false,
620        };
621        // To get minimum, need to find the first value that is not masked.
622        let first_unmasked = (0..self.len())
623            .zip(positions.iter().cycle())
624            .find(|(sequential_i, i)| **i != *sequential_i as u32)
625            .map(|(sequential_i, _)| sequential_i)
626            .unwrap();
627        let min = self.get(first_unmasked).unwrap();
628
629        let last_unmasked = (0..self.len())
630            .rev()
631            .zip(positions.iter().rev().cycle())
632            .filter(|(sequential_i, i)| **i != *sequential_i as u32)
633            .map(|(sequential_i, _)| sequential_i)
634            .next()
635            .unwrap();
636        let max = self.get(last_unmasked).unwrap();
637
638        let stats = SegmentStats {
639            min,
640            max,
641            count,
642            sorted,
643        };
644
645        let mut positions = positions.iter().copied().peekable();
646        let sequence = self.iter().enumerate().filter_map(move |(i, val)| {
647            if let Some(next_pos) = positions.peek()
648                && *next_pos == i as u32
649            {
650                positions.next();
651                return None;
652            }
653            Some(val)
654        });
655        *self = Self::from_stats_and_sequence(stats, sequence)
656    }
657}
658
659/// Segment reader that keeps its scan position across calls.
660pub struct SegmentCursor<'a> {
661    segment: &'a U64Segment,
662    state: SegmentCursorState,
663}
664
665#[derive(Debug, Default)]
666pub(crate) struct SegmentCursorState {
667    /// Byte the next select1 scan resumes at.
668    byte_idx: usize,
669    /// Set bits in the bitmap bytes before `byte_idx`.
670    ones_before: usize,
671}
672
673impl SegmentCursor<'_> {
674    /// The value at index `i`. A decreasing index rewinds the scan.
675    pub fn get(&mut self, i: usize) -> Option<u64> {
676        self.state.get(self.segment, i)
677    }
678}
679
680impl SegmentCursorState {
681    /// Append a contiguous range of values while preserving the bitmap scan
682    /// position for the next call.
683    pub(crate) fn extend_range(
684        &mut self,
685        segment: &U64Segment,
686        selection: Range<usize>,
687        values: &mut Vec<u64>,
688    ) {
689        let U64Segment::RangeWithBitmap { range, bitmap } = segment else {
690            match segment {
691                U64Segment::Range(range) => {
692                    let segment_len = (range.end - range.start) as usize;
693                    let end = selection.end.min(segment_len);
694                    if selection.start < end {
695                        values.extend(
696                            (range.start + selection.start as u64)..(range.start + end as u64),
697                        );
698                    }
699                }
700                _ => values.extend(selection.filter_map(|index| segment.get(index))),
701            }
702            return;
703        };
704
705        if selection.start < self.ones_before {
706            self.byte_idx = 0;
707            self.ones_before = 0;
708        }
709
710        while let Some(&byte) = bitmap.data.get(self.byte_idx) {
711            let ones = byte.count_ones() as usize;
712            let ones_after_byte = self.ones_before + ones;
713            if selection.start >= ones_after_byte {
714                self.ones_before = ones_after_byte;
715                self.byte_idx += 1;
716                continue;
717            }
718
719            let mut remaining_bits = byte;
720            let mut rank = self.ones_before;
721            while remaining_bits != 0 {
722                if rank >= selection.end {
723                    return;
724                }
725                let bit = remaining_bits.trailing_zeros() as usize;
726                if rank >= selection.start {
727                    values.push(range.start + (self.byte_idx * 8 + bit) as u64);
728                }
729                remaining_bits &= remaining_bits - 1;
730                rank += 1;
731            }
732
733            self.ones_before = ones_after_byte;
734            self.byte_idx += 1;
735            if self.ones_before >= selection.end {
736                return;
737            }
738        }
739    }
740
741    pub(crate) fn extend_dense_range(
742        &mut self,
743        segment: &U64Segment,
744        selection: Range<usize>,
745        values: &mut Vec<u64>,
746    ) {
747        let U64Segment::RangeWithBitmap { range, bitmap } = segment else {
748            self.extend_range(segment, selection, values);
749            return;
750        };
751        if selection.start < self.ones_before {
752            self.byte_idx = 0;
753            self.ones_before = 0;
754        }
755        self.extend_dense_bitmap_range(range.start, bitmap.bytes(), selection, values);
756    }
757
758    #[inline]
759    fn extend_dense_bitmap_range(
760        &mut self,
761        range_start: u64,
762        bitmap_bytes: &[u8],
763        selection: Range<usize>,
764        values: &mut Vec<u64>,
765    ) {
766        while let Some(&byte) = bitmap_bytes.get(self.byte_idx) {
767            let ones = byte.count_ones() as usize;
768            let ones_after_byte = self.ones_before + ones;
769            if selection.start >= ones_after_byte {
770                self.ones_before = ones_after_byte;
771                self.byte_idx += 1;
772                continue;
773            }
774
775            let includes_entire_byte =
776                selection.start <= self.ones_before && selection.end >= ones_after_byte;
777            if includes_entire_byte && ones >= 6 {
778                let byte_start = range_start + (self.byte_idx * 8) as u64;
779                if byte == u8::MAX {
780                    values.extend(byte_start..byte_start + 8);
781                } else {
782                    let mut remaining_bits = byte;
783                    let mut bit_offset = 0_u64;
784                    while remaining_bits != 0 {
785                        let zeros = remaining_bits.trailing_zeros();
786                        remaining_bits >>= zeros;
787                        bit_offset += u64::from(zeros);
788                        let run = remaining_bits.trailing_ones();
789                        values.extend(
790                            (byte_start + bit_offset)..(byte_start + bit_offset + u64::from(run)),
791                        );
792                        remaining_bits >>= run;
793                        bit_offset += u64::from(run);
794                    }
795                }
796                self.ones_before = ones_after_byte;
797                self.byte_idx += 1;
798                if self.ones_before >= selection.end {
799                    return;
800                }
801                continue;
802            }
803
804            let mut remaining_bits = byte;
805            let mut rank = self.ones_before;
806            while remaining_bits != 0 {
807                if rank >= selection.end {
808                    return;
809                }
810                let bit = remaining_bits.trailing_zeros() as usize;
811                if rank >= selection.start {
812                    values.push(range_start + (self.byte_idx * 8 + bit) as u64);
813                }
814                remaining_bits &= remaining_bits - 1;
815                rank += 1;
816            }
817
818            self.ones_before = ones_after_byte;
819            self.byte_idx += 1;
820            if self.ones_before >= selection.end {
821                return;
822            }
823        }
824    }
825
826    /// The value at index `i`. A decreasing index rewinds the scan.
827    pub(crate) fn get(&mut self, segment: &U64Segment, i: usize) -> Option<u64> {
828        let U64Segment::RangeWithBitmap { range, bitmap } = segment else {
829            return segment.get(i);
830        };
831        if i < self.ones_before {
832            self.byte_idx = 0;
833            self.ones_before = 0;
834        }
835        // Deserialization rejects a bitmap whose padding bits are set, so
836        // popcount counts only valid positions.
837        let mut remaining = i - self.ones_before;
838        let range_start = range.start;
839        let bitmap_bytes = bitmap.bytes();
840        while let Some(&byte) = bitmap_bytes.get(self.byte_idx) {
841            let ones = byte.count_ones() as usize;
842            if remaining < ones {
843                let mut b = byte;
844                for _ in 0..remaining {
845                    b &= b - 1; // clear lowest set bit
846                }
847                let bit = b.trailing_zeros() as usize;
848                return Some(range_start + (self.byte_idx * 8 + bit) as u64);
849            }
850            remaining -= ones;
851            self.ones_before += ones;
852            self.byte_idx += 1;
853        }
854        None
855    }
856}
857
858#[cfg(test)]
859mod test {
860    use super::*;
861
862    #[test]
863    fn test_range_with_bitmap_data_remains_publicly_mutable() {
864        let mut segment = U64Segment::RangeWithBitmap {
865            range: 0..8,
866            bitmap: Bitmap::new_empty(8),
867        };
868        let U64Segment::RangeWithBitmap { bitmap, .. } = &mut segment else {
869            unreachable!();
870        };
871
872        bitmap.data[0] = 0b1010_0101;
873        assert_eq!(bitmap.len, 8);
874        assert_eq!(bitmap.count_ones(), 4);
875    }
876
877    #[test]
878    fn test_extend_range_over_full_and_near_dense_bitmap_bytes() {
879        let mut bitmap = Bitmap::new_full(24);
880        bitmap.clear(10);
881        bitmap.clear(17);
882        bitmap.clear(22);
883        let segment = U64Segment::RangeWithBitmap {
884            range: 100..124,
885            bitmap,
886        };
887        assert!(segment.use_dense_range_expansion(segment.len()));
888
889        let mut sparse_bitmap = Bitmap::new_empty(24);
890        for i in [0, 8, 16] {
891            sparse_bitmap.set(i);
892        }
893        let sparse_segment = U64Segment::RangeWithBitmap {
894            range: 0..24,
895            bitmap: sparse_bitmap,
896        };
897        assert!(!sparse_segment.use_dense_range_expansion(sparse_segment.len()));
898        let expected = segment.iter().collect::<Vec<_>>();
899
900        let mut state = SegmentCursorState::default();
901        let mut actual = Vec::new();
902        for selection in [0..8, 8..15, 15..21] {
903            state.extend_dense_range(&segment, selection, &mut actual);
904        }
905        assert_eq!(actual, expected);
906
907        let mut state = SegmentCursorState::default();
908        let mut partial = Vec::new();
909        state.extend_dense_range(&segment, 9..20, &mut partial);
910        assert_eq!(partial, expected[9..20]);
911    }
912
913    #[test]
914    fn test_segments() {
915        fn check_segment(values: &[u64], expected: &U64Segment) {
916            let segment = U64Segment::from_slice(values);
917            assert_eq!(segment, *expected);
918            assert_eq!(values.len(), segment.len());
919
920            let roundtripped = segment.iter().collect::<Vec<_>>();
921            assert_eq!(roundtripped, values);
922
923            let expected_min = values.iter().copied().min();
924            let expected_max = values.iter().copied().max();
925            match segment.range() {
926                Some(range) => {
927                    assert_eq!(range.start(), &expected_min.unwrap());
928                    assert_eq!(range.end(), &expected_max.unwrap());
929                }
930                None => {
931                    assert_eq!(expected_min, None);
932                    assert_eq!(expected_max, None);
933                }
934            }
935
936            for (i, value) in values.iter().enumerate() {
937                assert_eq!(segment.get(i), Some(*value), "i = {}", i);
938                assert_eq!(segment.position(*value), Some(i), "i = {}", i);
939            }
940
941            check_segment_iter(&segment);
942        }
943
944        fn check_segment_iter(segment: &U64Segment) {
945            // Should be able to iterate forwards and backwards, and get the same thing.
946            let forwards = segment.iter().collect::<Vec<_>>();
947            let mut backwards = segment.iter().rev().collect::<Vec<_>>();
948            backwards.reverse();
949            assert_eq!(forwards, backwards);
950
951            // Should be able to pull from both sides in lockstep.
952            let mut expected = Vec::with_capacity(segment.len());
953            let mut actual = Vec::with_capacity(segment.len());
954            let mut iter = segment.iter();
955            // Alternating forwards and backwards
956            for i in 0..segment.len() {
957                if i % 2 == 0 {
958                    actual.push(iter.next().unwrap());
959                    expected.push(segment.get(i / 2).unwrap());
960                } else {
961                    let i = segment.len() - 1 - i / 2;
962                    actual.push(iter.next_back().unwrap());
963                    expected.push(segment.get(i).unwrap());
964                };
965            }
966            assert_eq!(expected, actual);
967        }
968
969        // Empty
970        check_segment(&[], &U64Segment::Range(0..0));
971
972        // Single value
973        check_segment(&[42], &U64Segment::Range(42..43));
974
975        // Contiguous range
976        check_segment(
977            &(100..200).collect::<Vec<_>>(),
978            &U64Segment::Range(100..200),
979        );
980
981        // Range with a hole
982        let values = (0..1000).filter(|&x| x != 100).collect::<Vec<_>>();
983        check_segment(
984            &values,
985            &U64Segment::RangeWithHoles {
986                range: 0..1000,
987                holes: vec![100].into(),
988            },
989        );
990
991        // Range with every other value missing
992        let values = (0..1000).filter(|&x| x % 2 == 0).collect::<Vec<_>>();
993        check_segment(
994            &values,
995            &U64Segment::RangeWithBitmap {
996                range: 0..999,
997                bitmap: Bitmap::from((0..999).map(|x| x % 2 == 0).collect::<Vec<_>>().as_slice()),
998            },
999        );
1000
1001        // Sparse but sorted sequence
1002        check_segment(
1003            &[1, 7000, 24000],
1004            &U64Segment::SortedArray(vec![1, 7000, 24000].into()),
1005        );
1006
1007        // Sparse unsorted sequence
1008        check_segment(
1009            &[7000, 1, 24000],
1010            &U64Segment::Array(vec![7000, 1, 24000].into()),
1011        );
1012    }
1013
1014    /// Decoding accepts an empty encoding of every variant, so `range()` must report the
1015    /// absence of extrema for all of them rather than unwrapping a value or computing
1016    /// `end - 1` on a zero-length range.
1017    #[test]
1018    fn test_empty_segments_have_no_range() {
1019        let empty: Vec<u64> = Vec::new();
1020        let segments = [
1021            U64Segment::Range(5..5),
1022            U64Segment::RangeWithHoles {
1023                range: 0..0,
1024                holes: empty.clone().into(),
1025            },
1026            U64Segment::RangeWithBitmap {
1027                range: 0..0,
1028                bitmap: Bitmap::new_empty(0),
1029            },
1030            U64Segment::SortedArray(empty.clone().into()),
1031            U64Segment::Array(empty.into()),
1032        ];
1033        for segment in segments {
1034            assert_eq!(segment.range(), None, "{segment:?} should have no range");
1035        }
1036    }
1037
1038    #[test]
1039    fn test_segment_overflow_boundary() {
1040        // Sparse range spanning i64::MAX — the original overflow reproducer.
1041        // n_holes ≈ 2^63, which overflows `4 * n_holes as usize` without u128 arithmetic.
1042        let values: Vec<u64> = vec![0, 1, 2, 100, i64::MAX as u64];
1043        let segment = U64Segment::from_slice(&values);
1044        assert!(
1045            matches!(segment, U64Segment::SortedArray(_)),
1046            "sparse range spanning i64::MAX should be SortedArray, got {:?}",
1047            std::mem::discriminant(&segment)
1048        );
1049        assert_eq!(segment.len(), 5);
1050        assert_eq!(segment.iter().collect::<Vec<_>>(), values);
1051
1052        // Two values at u64 extremes — triggers n_holes() total_slots overflow
1053        // (u64::MAX - 0 + 1 wraps to 0 without u128).
1054        let values: Vec<u64> = vec![0, u64::MAX];
1055        let segment = U64Segment::from_slice(&values);
1056        assert!(
1057            matches!(segment, U64Segment::SortedArray(_)),
1058            "full u64 span should be SortedArray, got {:?}",
1059            std::mem::discriminant(&segment)
1060        );
1061        assert_eq!(segment.len(), 2);
1062        assert_eq!(segment.iter().collect::<Vec<_>>(), values);
1063
1064        // Small dense set near u64::MAX — cost estimation correctly prefers a
1065        // range-backed encoding, but Range<u64> cannot represent u64::MAX + 1
1066        // as the exclusive end. Must fall back to SortedArray.
1067        let values: Vec<u64> = vec![u64::MAX - 3, u64::MAX - 1, u64::MAX];
1068        let segment = U64Segment::from_slice(&values);
1069        assert!(
1070            matches!(segment, U64Segment::SortedArray(_)),
1071            "dense set near u64::MAX should be SortedArray (exclusive end unrepresentable), got {:?}",
1072            std::mem::discriminant(&segment)
1073        );
1074        assert_eq!(segment.len(), 3);
1075        assert_eq!(segment.iter().collect::<Vec<_>>(), values);
1076
1077        // Single value at u64::MAX — contiguous range with n_holes == 0, but
1078        // exclusive end u64::MAX + 1 overflows.
1079        let values: Vec<u64> = vec![u64::MAX];
1080        let segment = U64Segment::from_slice(&values);
1081        assert!(
1082            matches!(segment, U64Segment::SortedArray(_)),
1083            "single u64::MAX should be SortedArray, got {:?}",
1084            std::mem::discriminant(&segment)
1085        );
1086        assert_eq!(segment.len(), 1);
1087        assert_eq!(segment.iter().collect::<Vec<_>>(), values);
1088
1089        // Contiguous range ending just below u64::MAX — exclusive end is
1090        // representable, so Range encoding should still be used.
1091        let values: Vec<u64> = vec![u64::MAX - 3, u64::MAX - 2, u64::MAX - 1];
1092        let segment = U64Segment::from_slice(&values);
1093        assert_eq!(segment, U64Segment::Range((u64::MAX - 3)..u64::MAX));
1094        assert_eq!(segment.len(), 3);
1095        assert_eq!(segment.iter().collect::<Vec<_>>(), values);
1096
1097        // Regression: normal dense range with few holes still picks RangeWithHoles.
1098        // Needs total_slots > 32 * n_holes for RangeWithHoles to beat RangeWithBitmap.
1099        let values: Vec<u64> = (100..1100).filter(|&x| x != 500).collect();
1100        let segment = U64Segment::from_slice(&values);
1101        assert_eq!(
1102            segment,
1103            U64Segment::RangeWithHoles {
1104                range: 100..1100,
1105                holes: vec![500].into(),
1106            }
1107        );
1108        assert_eq!(segment.len(), 999);
1109        assert_eq!(segment.iter().collect::<Vec<_>>(), values);
1110
1111        // Regression: small dense range with hole picks RangeWithBitmap.
1112        let values: Vec<u64> = vec![100, 101, 102, 103, 105];
1113        let segment = U64Segment::from_slice(&values);
1114        assert!(
1115            matches!(segment, U64Segment::RangeWithBitmap { .. }),
1116            "small dense range with hole should be RangeWithBitmap, got {:?}",
1117            std::mem::discriminant(&segment)
1118        );
1119        assert_eq!(segment.len(), 5);
1120        assert_eq!(segment.iter().collect::<Vec<_>>(), values);
1121    }
1122
1123    #[test]
1124    fn test_u128_byte_cost_to_usize() {
1125        assert_eq!(super::u128_byte_cost_to_usize(0), 0);
1126        assert_eq!(super::u128_byte_cost_to_usize(42), 42);
1127        assert_eq!(
1128            super::u128_byte_cost_to_usize(usize::MAX as u128),
1129            usize::MAX
1130        );
1131        assert_eq!(super::u128_byte_cost_to_usize(u128::MAX), usize::MAX);
1132    }
1133
1134    #[test]
1135    fn test_sorted_sequence_sizes_sparse_span_saturates_range_with_holes_cost() {
1136        let stats = super::SegmentStats {
1137            min: 0,
1138            max: i64::MAX as u64,
1139            count: 5,
1140            sorted: true,
1141        };
1142        let sizes = U64Segment::sorted_sequence_sizes(&stats);
1143        assert_eq!(sizes[0], usize::MAX);
1144        assert!(sizes[2] < sizes[0]);
1145    }
1146
1147    #[test]
1148    fn test_sorted_sequence_sizes_sorted_array_cost_saturates() {
1149        // Nearly full [0, u64::MAX] with one hole: count = u64::MAX, n_holes = 1.
1150        // SortedArray cost 24 + 2 * u64::MAX does not fit in usize on 64-bit.
1151        let stats = super::SegmentStats {
1152            min: 0,
1153            max: u64::MAX,
1154            count: u64::MAX,
1155            sorted: true,
1156        };
1157        let sizes = U64Segment::sorted_sequence_sizes(&stats);
1158        assert_eq!(sizes[2], usize::MAX);
1159    }
1160
1161    #[test]
1162    fn test_sorted_sequence_sizes_full_span_bitmap_cost() {
1163        // Synthetic stats: full [0, u64::MAX] slot space; exercises `range_with_bitmap`
1164        // cost path (always fits in `usize` on 64-bit targets).
1165        let stats = super::SegmentStats {
1166            min: 0,
1167            max: u64::MAX,
1168            count: 1,
1169            sorted: true,
1170        };
1171        let sizes = U64Segment::sorted_sequence_sizes(&stats);
1172        assert!(sizes[1] < sizes[0]);
1173        assert!(sizes[1] < usize::MAX);
1174    }
1175
1176    #[test]
1177    fn test_with_new_high() {
1178        // Test Range: contiguous sequence
1179        let segment = U64Segment::Range(10..20);
1180
1181        // Test adding value that extends the range
1182        let result = segment.clone().with_new_high(20).unwrap();
1183        assert_eq!(result, U64Segment::Range(10..21));
1184
1185        // Test adding value that creates holes
1186        let result = segment.with_new_high(25).unwrap();
1187        assert_eq!(
1188            result,
1189            U64Segment::RangeWithHoles {
1190                range: 10..26,
1191                holes: EncodedU64Array::U64(vec![20, 21, 22, 23, 24]),
1192            }
1193        );
1194
1195        // Test RangeWithHoles: sequence with existing holes
1196        let segment = U64Segment::RangeWithHoles {
1197            range: 10..20,
1198            holes: EncodedU64Array::U64(vec![15, 17]),
1199        };
1200
1201        // Test adding value that extends the range without new holes
1202        let result = segment.clone().with_new_high(20).unwrap();
1203        assert_eq!(
1204            result,
1205            U64Segment::RangeWithHoles {
1206                range: 10..21,
1207                holes: EncodedU64Array::U64(vec![15, 17]),
1208            }
1209        );
1210
1211        // Test adding value that creates additional holes
1212        let result = segment.with_new_high(25).unwrap();
1213        assert_eq!(
1214            result,
1215            U64Segment::RangeWithHoles {
1216                range: 10..26,
1217                holes: EncodedU64Array::U64(vec![15, 17, 20, 21, 22, 23, 24]),
1218            }
1219        );
1220
1221        // Test RangeWithBitmap: sequence with bitmap representation
1222        let mut bitmap = Bitmap::new_full(10);
1223        bitmap.clear(3); // Clear position 3 (value 13)
1224        bitmap.clear(7); // Clear position 7 (value 17)
1225        let segment = U64Segment::RangeWithBitmap {
1226            range: 10..20,
1227            bitmap,
1228        };
1229
1230        // Test adding value that extends the range without new holes
1231        let result = segment.clone().with_new_high(20).unwrap();
1232        let expected_bitmap = {
1233            let mut b = Bitmap::new_full(11);
1234            b.clear(3); // Clear position 3 (value 13)
1235            b.clear(7); // Clear position 7 (value 17)
1236            b
1237        };
1238        assert_eq!(
1239            result,
1240            U64Segment::RangeWithBitmap {
1241                range: 10..21,
1242                bitmap: expected_bitmap,
1243            }
1244        );
1245
1246        // Test adding value that creates additional holes
1247        let result = segment.with_new_high(25).unwrap();
1248        let expected_bitmap = {
1249            let mut b = Bitmap::new_full(16);
1250            b.clear(3); // Clear position 3 (value 13)
1251            b.clear(7); // Clear position 7 (value 17)
1252            // Clear positions 10-14 (values 20-24)
1253            for i in 10..15 {
1254                b.clear(i);
1255            }
1256            b
1257        };
1258        assert_eq!(
1259            result,
1260            U64Segment::RangeWithBitmap {
1261                range: 10..26,
1262                bitmap: expected_bitmap,
1263            }
1264        );
1265
1266        // Test SortedArray: sparse sorted sequence
1267        let segment = U64Segment::SortedArray(EncodedU64Array::U64(vec![1, 5, 10]));
1268
1269        let result = segment.with_new_high(15).unwrap();
1270        assert_eq!(
1271            result,
1272            U64Segment::SortedArray(EncodedU64Array::U64(vec![1, 5, 10, 15]))
1273        );
1274
1275        // Test Array: unsorted sequence
1276        let segment = U64Segment::Array(EncodedU64Array::U64(vec![10, 5, 1]));
1277
1278        let result = segment.with_new_high(15).unwrap();
1279        assert_eq!(
1280            result,
1281            U64Segment::Array(EncodedU64Array::U64(vec![10, 5, 1, 15]))
1282        );
1283
1284        // Test edge cases
1285        // Empty segment
1286        let segment = U64Segment::Range(0..0);
1287        let result = segment.with_new_high(5).unwrap();
1288        assert_eq!(result, U64Segment::Range(5..6));
1289
1290        // Single value segment
1291        let segment = U64Segment::Range(42..43);
1292        let result = segment.with_new_high(50).unwrap();
1293        assert_eq!(
1294            result,
1295            U64Segment::RangeWithHoles {
1296                range: 42..51,
1297                holes: EncodedU64Array::U64(vec![43, 44, 45, 46, 47, 48, 49]),
1298            }
1299        );
1300    }
1301
1302    #[test]
1303    fn test_with_new_high_assertion() {
1304        let segment = U64Segment::Range(10..20);
1305        // This should return an error because 15 is not higher than the current maximum 19
1306        let result = segment.with_new_high(15);
1307        assert!(result.is_err());
1308        let error = result.unwrap_err();
1309        assert!(
1310            error
1311                .to_string()
1312                .contains("New value 15 must be higher than current maximum 19")
1313        );
1314    }
1315
1316    #[test]
1317    fn test_with_new_high_assertion_equal() {
1318        let segment = U64Segment::Range(1..6);
1319        // This should return an error because 5 is not higher than the current maximum 5
1320        let result = segment.with_new_high(5);
1321        assert!(result.is_err());
1322        let error = result.unwrap_err();
1323        assert!(
1324            error
1325                .to_string()
1326                .contains("New value 5 must be higher than current maximum 5")
1327        );
1328    }
1329
1330    #[test]
1331    fn test_contains() {
1332        // Test Range: contiguous sequence
1333        let segment = U64Segment::Range(10..20);
1334        assert!(segment.contains(10), "Should contain 10");
1335        assert!(segment.contains(15), "Should contain 15");
1336        assert!(segment.contains(19), "Should contain 19");
1337        assert!(!segment.contains(9), "Should not contain 9");
1338        assert!(!segment.contains(20), "Should not contain 20");
1339        assert!(!segment.contains(25), "Should not contain 25");
1340
1341        // Test RangeWithHoles: sequence with holes
1342        let segment = U64Segment::RangeWithHoles {
1343            range: 10..20,
1344            holes: EncodedU64Array::U64(vec![15, 17]),
1345        };
1346        assert!(segment.contains(10), "Should contain 10");
1347        assert!(segment.contains(14), "Should contain 14");
1348        assert!(!segment.contains(15), "Should not contain 15 (hole)");
1349        assert!(segment.contains(16), "Should contain 16");
1350        assert!(!segment.contains(17), "Should not contain 17 (hole)");
1351        assert!(segment.contains(18), "Should contain 18");
1352        assert!(
1353            !segment.contains(20),
1354            "Should not contain 20 (out of range)"
1355        );
1356
1357        // Test RangeWithBitmap: sequence with bitmap
1358        let mut bitmap = Bitmap::new_full(10);
1359        bitmap.clear(3); // Clear position 3 (value 13)
1360        bitmap.clear(7); // Clear position 7 (value 17)
1361        let segment = U64Segment::RangeWithBitmap {
1362            range: 10..20,
1363            bitmap,
1364        };
1365        assert!(segment.contains(10), "Should contain 10");
1366        assert!(segment.contains(12), "Should contain 12");
1367        assert!(
1368            !segment.contains(13),
1369            "Should not contain 13 (cleared in bitmap)"
1370        );
1371        assert!(segment.contains(16), "Should contain 16");
1372        assert!(
1373            !segment.contains(17),
1374            "Should not contain 17 (cleared in bitmap)"
1375        );
1376        assert!(segment.contains(19), "Should contain 19");
1377        assert!(
1378            !segment.contains(20),
1379            "Should not contain 20 (out of range)"
1380        );
1381
1382        // Test SortedArray: sparse sorted sequence
1383        let segment = U64Segment::SortedArray(EncodedU64Array::U64(vec![1, 5, 10]));
1384        assert!(segment.contains(1), "Should contain 1");
1385        assert!(segment.contains(5), "Should contain 5");
1386        assert!(segment.contains(10), "Should contain 10");
1387        assert!(!segment.contains(0), "Should not contain 0");
1388        assert!(!segment.contains(3), "Should not contain 3");
1389        assert!(!segment.contains(15), "Should not contain 15");
1390
1391        // Test Array: unsorted sequence
1392        let segment = U64Segment::Array(EncodedU64Array::U64(vec![10, 5, 1]));
1393        assert!(segment.contains(1), "Should contain 1");
1394        assert!(segment.contains(5), "Should contain 5");
1395        assert!(segment.contains(10), "Should contain 10");
1396        assert!(!segment.contains(0), "Should not contain 0");
1397        assert!(!segment.contains(3), "Should not contain 3");
1398        assert!(!segment.contains(15), "Should not contain 15");
1399
1400        // Test empty segment
1401        let segment = U64Segment::Range(0..0);
1402        assert!(
1403            !segment.contains(0),
1404            "Empty segment should not contain anything"
1405        );
1406        assert!(
1407            !segment.contains(5),
1408            "Empty segment should not contain anything"
1409        );
1410    }
1411}