use crate::{
bitpack::{bitunpack_core, bitunpack_core_div, packed_byte_size},
error::{Error, Result},
float::AlpFloat,
params::AlpParams,
};
#[inline(always)]
pub unsafe fn decode_standard_raw<F: AlpFloat>(
src: &[u8],
count: usize,
params: AlpParams,
dst_ptr: *mut F,
) -> Result<()> {
let mut cursor = 0;
if src.len() < cursor + F::BASE_SIZE {
return Err(Error::UnexpectedEof {
needed: cursor + F::BASE_SIZE,
available: src.len(),
});
}
let base = F::read_base(&src[cursor..cursor + F::BASE_SIZE]);
cursor += F::BASE_SIZE;
let (exp_factor, fac_int, frac_flt) = params.factors::<F>();
if params.bit_width == 0 {
let val = if params.use_div {
F::decode_from_int_div(base, exp_factor)
} else {
F::decode_from_int(base, fac_int, frac_flt)
};
for i in 0..count {
unsafe {
*dst_ptr.add(i) = val;
}
}
} else {
let packed_len = packed_byte_size(count, params.bit_width);
if src.len() < cursor + packed_len {
return Err(Error::UnexpectedEof {
needed: cursor + packed_len,
available: src.len(),
});
}
if params.use_div {
unsafe {
bitunpack_core_div(
&src[cursor..cursor + packed_len],
count,
params.bit_width,
base,
exp_factor,
dst_ptr,
);
}
} else {
unsafe {
bitunpack_core(
&src[cursor..cursor + packed_len],
count,
params.bit_width,
base,
fac_int,
frac_flt,
dst_ptr,
);
}
}
cursor += packed_len;
}
unsafe {
super::patch_exceptions(&src[cursor..], count, dst_ptr)?;
}
Ok(())
}
#[inline(always)]
pub fn decode_standard_slice<F: AlpFloat>(
src: &[u8],
count: usize,
params: AlpParams,
dst: &mut [F],
) -> Result<()> {
if dst.len() < count {
return Err(Error::BufferTooSmall {
needed: count,
available: dst.len(),
});
}
unsafe { decode_standard_raw(src, count, params, dst.as_mut_ptr()) }
}
pub fn decode_standard<F: AlpFloat>(
src: &[u8],
count: usize,
params: AlpParams,
dst: &mut Vec<F>,
) -> Result<()> {
let old_len = dst.len();
dst.reserve(count);
unsafe {
decode_standard_raw(src, count, params, dst.as_mut_ptr().add(old_len))?;
dst.set_len(old_len + count);
}
Ok(())
}