use std::marker::PhantomData;
use pco::ChunkConfig;
use pco::standalone::{simple_compress, simple_decompress, simple_decompress_into};
use crate::{Error, Result, impl_bytes_value_strategy, likely};
use super::{
super::inner::CompressionStrategy,
value::{AsInnerSlice, FromInnerSlice, PcoVecValue},
};
fn chunk_config() -> ChunkConfig {
ChunkConfig::default().with_enable_8_bit(true)
}
#[derive(Debug, Clone, Copy)]
pub struct PcodecStrategy<T>(PhantomData<T>);
impl_bytes_value_strategy!(PcodecStrategy, PcoVecValue);
impl<T> CompressionStrategy<T> for PcodecStrategy<T>
where
T: PcoVecValue,
{
fn compress(values: &[T]) -> Result<Vec<u8>> {
Ok(simple_compress(values.as_inner_slice(), &chunk_config())?)
}
fn decompress(bytes: &[u8], expected_len: usize) -> Result<Vec<T>> {
let vec: Vec<T::NumberType> = simple_decompress(bytes)?;
let vec = T::from_inner_slice(vec);
if likely(vec.len() == expected_len) {
return Ok(vec);
}
Err(Error::DecompressionMismatch {
expected_len,
actual_len: vec.len(),
})
}
#[inline]
fn decompress_into(bytes: &[u8], expected_len: usize, dst: &mut Vec<T>) -> Result<()> {
dst.clear();
Self::decompress_append(bytes, expected_len, dst)
}
#[inline]
fn decompress_append(bytes: &[u8], expected_len: usize, dst: &mut Vec<T>) -> Result<()> {
dst.reserve(expected_len);
let old_len = dst.len();
let spare = dst.spare_capacity_mut();
let slice = unsafe {
std::slice::from_raw_parts_mut(spare.as_mut_ptr().cast::<T::NumberType>(), expected_len)
};
let progress = simple_decompress_into(bytes, slice)?;
unsafe {
dst.set_len(old_len + progress.n_processed);
}
if likely(progress.n_processed == expected_len) {
return Ok(());
}
Err(Error::DecompressionMismatch {
expected_len,
actual_len: progress.n_processed,
})
}
}