use crate::{decoder::PhysicalPageScheduler, format::pb};
use self::{
basic::BasicPageScheduler, bitmap::DenseBitmapScheduler, fixed_size_list::FixedListScheduler,
value::ValuePageScheduler,
};
pub mod basic;
pub mod bitmap;
pub mod buffers;
pub mod fixed_size_list;
pub mod value;
#[derive(Clone, Copy, Debug)]
pub struct FileBuffers<'a> {
pub positions: &'a Vec<u64>,
}
#[derive(Clone, Copy, Debug)]
pub struct ColumnBuffers<'a, 'b> {
pub file_buffers: FileBuffers<'a>,
pub positions: &'b Vec<u64>,
}
#[derive(Clone, Copy, Debug)]
pub struct PageBuffers<'a, 'b, 'c> {
pub column_buffers: ColumnBuffers<'a, 'b>,
pub positions: &'c Vec<u64>,
}
fn get_buffer(buffer_desc: &pb::Buffer, buffers: &PageBuffers) -> u64 {
match pb::buffer::BufferType::try_from(buffer_desc.buffer_type).unwrap() {
pb::buffer::BufferType::Page => buffers.positions[buffer_desc.buffer_index as usize],
pb::buffer::BufferType::Column => {
buffers.column_buffers.positions[buffer_desc.buffer_index as usize]
}
pb::buffer::BufferType::File => {
buffers.column_buffers.file_buffers.positions[buffer_desc.buffer_index as usize]
}
}
}
fn get_buffer_decoder(
encoding: &pb::Flat,
buffers: &PageBuffers,
) -> Box<dyn PhysicalPageScheduler> {
match encoding.bits_per_value {
1 => Box::new(DenseBitmapScheduler::new(get_buffer(
encoding.buffer.as_ref().unwrap(),
buffers,
))),
bits_per_value => {
if bits_per_value % 8 != 0 {
todo!("bits_per_value that are not multiples of 8");
}
Box::new(ValuePageScheduler::new(
bits_per_value / 8,
get_buffer(encoding.buffer.as_ref().unwrap(), buffers),
))
}
}
}
pub fn decoder_from_array_encoding(
encoding: &pb::ArrayEncoding,
buffers: &PageBuffers,
) -> Box<dyn PhysicalPageScheduler> {
match encoding.array_encoding.as_ref().unwrap() {
pb::array_encoding::ArrayEncoding::Nullable(basic) => {
match basic.nullability.as_ref().unwrap() {
pb::nullable::Nullability::NoNulls(no_nulls) => {
Box::new(BasicPageScheduler::new_non_nullable(
decoder_from_array_encoding(no_nulls.values.as_ref().unwrap(), buffers),
))
}
pb::nullable::Nullability::SomeNulls(some_nulls) => {
Box::new(BasicPageScheduler::new_nullable(
decoder_from_array_encoding(some_nulls.validity.as_ref().unwrap(), buffers),
decoder_from_array_encoding(some_nulls.values.as_ref().unwrap(), buffers),
))
}
pb::nullable::Nullability::AllNulls(_) => {
Box::new(BasicPageScheduler::new_all_null())
}
}
}
pb::array_encoding::ArrayEncoding::Flat(flat) => get_buffer_decoder(flat, buffers),
pb::array_encoding::ArrayEncoding::FixedSizeList(fixed_size_list) => {
let item_encoding = fixed_size_list.items.as_ref().unwrap();
let item_scheduler = decoder_from_array_encoding(item_encoding, buffers);
Box::new(FixedListScheduler::new(
item_scheduler,
fixed_size_list.dimension,
))
}
pb::array_encoding::ArrayEncoding::List(list) => {
decoder_from_array_encoding(list.offsets.as_ref().unwrap(), buffers)
}
pb::array_encoding::ArrayEncoding::Struct(_) => unreachable!(),
}
}