use bitvec::prelude::BitVec;
use smallvec::SmallVec;
use crate::array::{ArrayImpl, DataChunk};
pub type PackedVec<T> = SmallVec<[T; 16]>;
#[derive(Clone)]
pub struct StorageChunk {
visibility: Option<BitVec>,
arrays: PackedVec<ArrayImpl>,
cardinality: usize,
}
impl StorageChunk {
pub fn construct(
visibility: Option<BitVec>,
arrays: SmallVec<[ArrayImpl; 16]>,
) -> Option<Self> {
assert!(!arrays.is_empty());
let first_length = arrays[0].len();
for array in &arrays {
assert_eq!(first_length, array.len());
}
let cardinality = if let Some(ref visibility) = visibility {
assert_eq!(visibility.len(), first_length);
visibility.count_ones()
} else {
first_length
};
if cardinality > 0 {
Some(Self {
visibility,
arrays,
cardinality,
})
} else {
None
}
}
pub fn cardinality(&self) -> usize {
self.cardinality
}
pub fn row_count(&self) -> usize {
self.array_at(0).len()
}
pub fn column_count(&self) -> usize {
self.arrays.len()
}
pub fn arrays(&self) -> &[ArrayImpl] {
&self.arrays
}
pub fn array_at(&self, idx: usize) -> &ArrayImpl {
&self.arrays[idx]
}
pub fn visibility(&self) -> &Option<BitVec> {
&self.visibility
}
pub fn to_data_chunk(self) -> DataChunk {
if self.arrays.is_empty() {
return DataChunk::no_column(self.cardinality);
}
match self.visibility {
Some(visibility) => DataChunk::from_iter(
self.arrays
.iter()
.map(|a| a.filter(&visibility.iter().map(|x| *x).collect::<Vec<bool>>())),
),
None => DataChunk::from_iter(self.arrays),
}
}
}