pub trait BitPackOps {
// Required methods
fn pack(
&self,
decompressed: &[u32],
compressed: &mut [u8],
num_bits: u8,
) -> usize;
fn unpack(
&self,
compressed: &[u8],
decompressed: &mut [u32],
num_bits: u8,
) -> usize;
fn pack_m1(
&self,
decompressed: &[u32],
compressed: &mut [u8],
num_bits: u8,
) -> usize;
fn unpack_m1(
&self,
compressed: &[u8],
decompressed: &mut [u32],
num_bits: u8,
) -> usize;
fn pack_d1(
&self,
decompressed: &[u32],
compressed: &mut [u8],
num_bits: u8,
) -> usize;
fn unpack_d1(
&self,
initial: u32,
compressed: &[u8],
decompressed: &mut [u32],
num_bits: u8,
) -> usize;
fn pack_d1z(
&self,
decompressed: &[u32],
compressed: &mut [u8],
num_bits: u8,
) -> usize;
fn unpack_d1z(
&self,
initial: u32,
compressed: &[u8],
decompressed: &mut [u32],
num_bits: u8,
) -> usize;
}Expand description
§Wrappers of the orignial bitpacking trait
The panic rules of compressed and decompressed array data are exactly the same as bitpacking crate. Details can
be found in bitpacking::BitPacker.
§Note:
- The
num_bitsparameter inpack*methods can be set to 0, which means to detect actualnum_bitsby internally callbitpacker.num_bits()orbitpacker.num_bits_sorted()
§Examples
Here are some examples for the variant bitpacking formats (from tests.rs):
use bitpacking_plus::BitPackOps;
use bitpacking::{BitPacker, BitPacker1x, BitPacker4x, BitPacker8x};
use rand::{thread_rng, Rng};
#[derive(Debug)]
enum PackMethod {
Vanilla,
M1,
D1,
D1Z,
}
fn test_unpack_helper(
bitpacker: &dyn BitPackOps,
decompressed: &[u32],
compressed: &mut [u8],
block_size: usize,
pack_method: PackMethod,
) {
// We only test one block.
println!("Test method: {:?}\nBlock size: {}", &pack_method, &block_size);
let initial = decompressed[0];
let n1 = match pack_method {
PackMethod::Vanilla => {
bitpacker.pack(decompressed.get(0..block_size).unwrap(), compressed, 0)
}
PackMethod::M1 => {
bitpacker.pack_m1(decompressed.get(0..block_size).unwrap(), compressed, 0)
}
PackMethod::D1 => {
bitpacker.pack_d1(decompressed.get(0..block_size).unwrap(), compressed, 0)
}
PackMethod::D1Z => {
bitpacker.pack_d1z(decompressed.get(0..block_size).unwrap(), compressed, 0)
}
};
let num_bits = 8 * n1 / block_size;
let mut new_decompressed = [0_u32; 256];
let n2 = match pack_method {
PackMethod::Vanilla => bitpacker.unpack(compressed, &mut new_decompressed, num_bits as u8),
PackMethod::M1 => bitpacker.unpack_m1(compressed, &mut new_decompressed, num_bits as u8),
PackMethod::D1 => {
bitpacker.unpack_d1(initial, compressed, &mut new_decompressed, num_bits as u8)
}
PackMethod::D1Z => {
bitpacker.unpack_d1z(initial, compressed, &mut new_decompressed, num_bits as u8)
}
};
assert_eq!(n1, n2);
assert_eq!(
decompressed.get(0..block_size).unwrap(),
new_decompressed.get(0..block_size).unwrap()
);
println!("Bytes used: {}", n1);
println!(
"Decompresed: {:?}\n",
new_decompressed.get(0..block_size).unwrap()
);
}
fn main() {
let mut my_data: [u32; 256] = [(); 256].map(|_| thread_rng().gen_range(0..20000));
println!("Orignial: {:?}\n", my_data);
let mut compressed = [0_u8; 8192];
let bitpacker4 = BitPacker4x::new();
test_unpack_helper(&bitpacker4, &my_data, &mut compressed, BitPacker4x::BLOCK_LEN, PackMethod::Vanilla);
test_unpack_helper(&bitpacker4, &my_data, &mut compressed, BitPacker4x::BLOCK_LEN, PackMethod::M1);
test_unpack_helper(&bitpacker4, &my_data, &mut compressed, BitPacker4x::BLOCK_LEN, PackMethod::D1Z);
// For `(un)pack_d1`, the decompressed data must be sorted.
my_data.sort();
test_unpack_helper(&bitpacker4, &my_data, &mut compressed, BitPacker4x::BLOCK_LEN, PackMethod::D1);
}