use arrow::buffer::NullBuffer;
use bytes::Bytes;
use crate::{error::Result, memory::EstimateMemory};
pub mod boolean;
pub mod byte;
pub mod decimal;
pub mod float;
pub mod integer;
mod rle;
pub mod timestamp;
mod util;
pub trait PrimitiveValueEncoder<V: Copy>: EstimateMemory {
fn new() -> Self;
fn write_one(&mut self, value: V);
fn write_slice(&mut self, values: &[V]) {
for &value in values {
self.write_one(value);
}
}
fn take_inner(&mut self) -> Bytes;
}
pub trait PrimitiveValueDecoder<V> {
fn skip(&mut self, n: usize) -> Result<()>;
fn decode(&mut self, out: &mut [V]) -> Result<()>;
fn decode_spaced(&mut self, out: &mut [V], present: &NullBuffer) -> Result<()> {
debug_assert_eq!(out.len(), present.len());
let non_null_count = present.len() - present.null_count();
if non_null_count == 0 {
return Ok(());
}
let range_start = out.len() - non_null_count;
self.decode(&mut out[range_start..])?;
if non_null_count == present.len() {
return Ok(());
}
let head_indices = range_start..out.len();
for (correct_index, head_index) in present.valid_indices().zip(head_indices) {
out.swap(correct_index, head_index);
}
Ok(())
}
}
#[cfg(test)]
mod tests {
use proptest::prelude::*;
use super::*;
struct DummyDecoder {
value: i32,
}
impl DummyDecoder {
fn new() -> Self {
Self { value: 0 }
}
}
impl PrimitiveValueDecoder<i32> for DummyDecoder {
fn skip(&mut self, n: usize) -> Result<()> {
self.value += n as i32;
Ok(())
}
fn decode(&mut self, out: &mut [i32]) -> Result<()> {
let values = (0..out.len())
.map(|x| self.value + x as i32)
.collect::<Vec<_>>();
out.copy_from_slice(&values);
self.value += out.len() as i32;
Ok(())
}
}
fn gen_spaced_dummy_decoder_expected(present: &[bool]) -> Vec<i32> {
let mut value = 0;
let mut expected = vec![];
for &is_present in present {
if is_present {
expected.push(value);
value += 1;
} else {
expected.push(-1);
}
}
expected
}
proptest! {
#[test]
fn decode_spaced_proptest(present: Vec<bool>) {
let mut decoder = DummyDecoder::new();
let mut out = vec![-1; present.len()];
decoder.decode_spaced(&mut out, &NullBuffer::from(present.clone())).unwrap();
let expected = gen_spaced_dummy_decoder_expected(&present);
prop_assert_eq!(out, expected);
}
}
#[test]
fn decode_spaced_edge_cases() {
let mut decoder = DummyDecoder::new();
let len = 10;
let mut out = vec![-1; len];
let present = vec![true; len];
let present = NullBuffer::from(present);
decoder.decode_spaced(&mut out, &present).unwrap();
let expected: Vec<_> = (0..len).map(|i| i as i32).collect();
assert_eq!(out, expected);
let mut out = vec![-1; len];
let present = vec![false; len];
let present = NullBuffer::from(present);
decoder.decode_spaced(&mut out, &present).unwrap();
let expected = vec![-1; len];
assert_eq!(out, expected);
}
#[test]
fn test_skip() {
let mut decoder = DummyDecoder::new();
decoder.skip(10).unwrap();
let mut out = vec![-1; 1];
decoder.decode(&mut out).unwrap();
assert_eq!(out, vec![10]);
decoder.skip(10).unwrap();
let mut out2 = vec![-1; 5];
decoder.decode(&mut out2).unwrap();
assert_eq!(out2, vec![21, 22, 23, 24, 25]);
}
}