mod consumer;
mod decoder;
pub(crate) mod kernel;
pub use consumer::{AlpConsumer, AlpDeltaConsumer, ForConsumer, RawU64Consumer};
pub use decoder::{
AlpDecoder, AlpDictDecoder, AlpDivDecoder, AlpFac1Decoder, AlpMulDecoder, AlpRdConstantDecoder,
};
pub(crate) use kernel::dispatch_bw;
use crate::{
bitpack::packed_byte_size,
error::{Error, Result},
float::AlpFloat,
};
#[inline]
pub unsafe fn bitunpack_core_consumer<T: Copy, C: AlpConsumer<T>>(
src: &[u8],
count: usize,
bit_width: u8,
mut consumer: C,
dst_ptr: *mut T,
) {
if count == 0 {
return;
}
debug_assert!(bit_width <= 64, "bit_width must be in 0..=64");
if bit_width == 0 {
unsafe {
consumer.consume_zeros(count, dst_ptr);
}
return;
}
unsafe {
dispatch_bw!(
bit_width,
src.as_ptr(),
count,
&mut consumer,
dst_ptr,
src.len()
);
}
}
#[inline]
pub unsafe fn bitunpack_core_generic<F: AlpFloat, D: AlpDecoder<F>>(
src: &[u8],
count: usize,
bit_width: u8,
decoder: D,
dst_ptr: *mut F,
) {
unsafe {
bitunpack_core_consumer(src, count, bit_width, ForConsumer::new(decoder), dst_ptr);
}
}
#[inline]
pub(crate) unsafe fn bitunpack_u64_raw(
src: &[u8],
count: usize,
bit_width: u8,
dst_ptr: *mut u64,
) -> Result<()> {
if count == 0 {
return Ok(());
}
if bit_width > 64 {
return Err(Error::UnsupportedParams {
exp: 0,
fac: 0,
bit_width,
});
}
let required_bytes = packed_byte_size(count, bit_width);
if src.len() < required_bytes {
return Err(Error::UnexpectedEof {
needed: required_bytes,
available: src.len(),
});
}
unsafe {
bitunpack_core_consumer(src, count, bit_width, RawU64Consumer, dst_ptr);
}
Ok(())
}
pub fn bitunpack_u64_slice(src: &[u8], count: usize, bit_width: u8, dst: &mut [u64]) -> Result<()> {
if count == 0 {
return Ok(());
}
if dst.len() < count {
return Err(Error::BufferTooSmall {
needed: count,
available: dst.len(),
});
}
unsafe { bitunpack_u64_raw(src, count, bit_width, dst.as_mut_ptr()) }
}
#[inline]
pub fn bitunpack_u64(src: &[u8], count: usize, bit_width: u8, dst: &mut Vec<u64>) -> Result<()> {
if count == 0 {
return Ok(());
}
let old_len = dst.len();
dst.reserve(count);
unsafe {
bitunpack_u64_raw(src, count, bit_width, dst.as_mut_ptr().add(old_len))?;
dst.set_len(old_len + count);
}
Ok(())
}