use super::{CompressResult, CompressionError, Compressor};
use crate::bitmask::{packing, rle};
pub struct RleCompressor;
impl Compressor for RleCompressor {
fn compress(&self, data: &[u8]) -> Result<CompressResult, CompressionError> {
let n_elements = data.len() * 8;
let bits = packing::unpack(data, n_elements)
.map_err(|e| CompressionError::Unknown(format!("RLE compress unpack: {e}")))?;
let rle_bytes = rle::encode(&bits);
let mut out = Vec::with_capacity(4 + rle_bytes.len());
out.extend_from_slice(&(n_elements as u32).to_be_bytes());
out.extend_from_slice(&rle_bytes);
Ok(CompressResult {
data: out,
block_offsets: None,
})
}
fn decompress(&self, data: &[u8], expected_size: usize) -> Result<Vec<u8>, CompressionError> {
let Some((prefix, rle_bytes)) = data.split_first_chunk::<4>() else {
return Err(CompressionError::Unknown(
"RLE blob too short: missing 4-byte n_elements prefix".to_string(),
));
};
let n_elements = u32::from_be_bytes(*prefix) as usize;
let bits = rle::decode(rle_bytes, n_elements)
.map_err(|e| CompressionError::Unknown(format!("RLE decode: {e}")))?;
let packed = packing::pack(&bits)
.map_err(|e| CompressionError::Unknown(format!("RLE repack: {e}")))?;
if packed.len() != expected_size {
return Err(CompressionError::Unknown(format!(
"RLE decompressed size {} != expected {}",
packed.len(),
expected_size
)));
}
Ok(packed)
}
fn decompress_range(
&self,
_data: &[u8],
_block_offsets: &[u64],
_byte_pos: usize,
_byte_size: usize,
) -> Result<Vec<u8>, CompressionError> {
Err(CompressionError::RangeNotSupported)
}
}