molframe_core/column/encoded/
iter.rs1use super::super::bits::unpack_one;
4use super::model::{ColumnValue, EncodedColumn};
5
6#[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}