use better_io::BetterBufRead;
use std::marker::PhantomData;
use crate::chunk_latent_decompressor::DynChunkLatentDecompressor;
use crate::data_types::Number;
use crate::errors::{PcoError, PcoResult};
use crate::metadata::{ChunkMeta, LatentVarKey, PerLatentVar};
use crate::wrapped::PageDecompressor;
#[derive(Clone, Debug)]
pub struct ChunkDecompressorInner {
pub(crate) meta: ChunkMeta,
pub(crate) per_latent_var: PerLatentVar<DynChunkLatentDecompressor>,
}
impl ChunkDecompressorInner {
fn new(meta: ChunkMeta) -> PcoResult<Self> {
let per_latent_var = meta.per_latent_var.as_ref().map_result(|key, latent_var| {
let delta_encoding = meta.delta_encoding.for_latent_var(key);
DynChunkLatentDecompressor::create(latent_var, delta_encoding)
})?;
Ok(Self {
meta,
per_latent_var,
})
}
pub fn n_latents_per_delta_state(&self) -> usize {
self
.meta
.delta_encoding
.for_latent_var(LatentVarKey::Primary)
.n_latents_per_state()
}
}
#[derive(Clone, Debug)]
pub struct ChunkDecompressor<T: Number> {
pub(crate) inner: ChunkDecompressorInner,
phantom: PhantomData<T>,
}
impl<T: Number> ChunkDecompressor<T> {
pub(crate) fn new(meta: ChunkMeta) -> PcoResult<Self> {
if !T::mode_is_valid(&meta.mode) {
return Err(PcoError::corruption(format!(
"invalid mode for {} number type: {:?}",
std::any::type_name::<T>(),
meta.mode
)));
}
let inner = ChunkDecompressorInner::new(meta)?;
Ok(Self {
inner,
phantom: PhantomData,
})
}
pub fn meta(&self) -> &ChunkMeta {
&self.inner.meta
}
pub fn page_decompressor<R: BetterBufRead>(
&mut self,
src: R,
n: usize,
) -> PcoResult<PageDecompressor<'_, T, R>> {
PageDecompressor::<T, R>::new(src, self, n)
}
}