Skip to main content

molframe_core/column/encoded/
iter.rs

1//! Linear iteration over encoded columns.
2
3use super::super::bits::unpack_one;
4use super::model::{ColumnValue, EncodedColumn};
5
6/// Sequential reader over an encoded column.
7#[derive(Debug)]
8pub struct ColumnIter<'a, T> {
9    column: &'a EncodedColumn<T>,
10    position: u32,
11    running: i64,
12    run: usize,
13}
14
15impl<'a, T> ColumnIter<'a, T> {
16    pub(super) const fn new(column: &'a EncodedColumn<T>) -> Self {
17        Self {
18            column,
19            position: 0,
20            running: 0,
21            run: 0,
22        }
23    }
24}
25
26impl<T: ColumnValue> Iterator for ColumnIter<'_, T> {
27    type Item = T;
28
29    fn next(&mut self) -> Option<T> {
30        if self.position as usize >= self.column.len() {
31            return None;
32        }
33        let value = match self.column {
34            EncodedColumn::Plain(values) => copied_at(values, self.position)?,
35            EncodedColumn::Constant { value, .. } => *value,
36            EncodedColumn::RunLength { values, run_ends } => {
37                next_run_length(values, run_ends, self.position, &mut self.run)?
38            }
39            EncodedColumn::BitPacked { data, width, .. } => {
40                T::from_bits(unpack_one(data, *width, self.position)?)?
41            }
42            EncodedColumn::Delta { first, deltas, .. } => {
43                next_delta(*first, deltas, self.position, &mut self.running)?
44            }
45        };
46        self.position = self.position.checked_add(1)?;
47        Some(value)
48    }
49
50    fn size_hint(&self) -> (usize, Option<usize>) {
51        let remaining = self.column.len() - self.position as usize;
52        (remaining, Some(remaining))
53    }
54}
55
56fn copied_at<T: Copy>(values: &[T], position: u32) -> Option<T> {
57    values.get(usize::try_from(position).ok()?).copied()
58}
59
60fn next_run_length<T: Copy>(
61    values: &[T],
62    run_ends: &[u32],
63    position: u32,
64    run: &mut usize,
65) -> Option<T> {
66    while run_ends.get(*run).is_some_and(|end| *end <= position) {
67        *run += 1;
68    }
69    values.get(*run).copied()
70}
71
72fn next_delta<T: ColumnValue>(
73    first: T,
74    deltas: &[i32],
75    position: u32,
76    running: &mut i64,
77) -> Option<T> {
78    if position == 0 {
79        *running = first.to_bits().cast_signed();
80    } else {
81        let index = usize::try_from(position.checked_sub(1)?).ok()?;
82        *running += i64::from(*deltas.get(index)?);
83    }
84    T::from_bits((*running).cast_unsigned())
85}
86
87impl<T: ColumnValue> ExactSizeIterator for ColumnIter<'_, T> {}
88
89impl<'a, T: ColumnValue> IntoIterator for &'a EncodedColumn<T> {
90    type Item = T;
91    type IntoIter = ColumnIter<'a, T>;
92    fn into_iter(self) -> Self::IntoIter {
93        self.iter()
94    }
95}