pub fn extract_packed_le(data: &[u8], bit_start: usize, bit_width: usize) -> u32 {
let mut value = 0u32;
for i in 0..bit_width {
let bit_idx = bit_start + i;
let byte = data[bit_idx >> 3];
let bit = (byte >> (bit_idx & 7)) & 1;
value |= (bit as u32) << i;
}
value
}
pub fn pack_packed_le(values: &[u16], bit_width: usize) -> Vec<u8> {
let total_bits = values.len() * bit_width;
let mut out = vec![0u8; total_bits.div_ceil(8)];
let mut bit_idx = 0usize;
for &value in values {
for i in 0..bit_width {
let bit = ((value >> i) & 1) as u8;
let byte_idx = bit_idx >> 3;
let bit_pos = bit_idx & 7;
out[byte_idx] |= bit << bit_pos;
bit_idx += 1;
}
}
out
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_pack_and_extract_packed_le_roundtrip() {
let values = [0x0001, 0x0002, 0x0123, 0x03ff];
let packed = pack_packed_le(&values, 10);
let decoded: Vec<u32> = (0..values.len())
.map(|i| extract_packed_le(&packed, i * 10, 10))
.collect();
assert_eq!(decoded, values.iter().map(|&v| v as u32).collect::<Vec<_>>());
}
#[test]
fn test_pack_packed_le_uses_minimum_byte_length() {
let packed = pack_packed_le(&[0b101, 0b011], 3);
assert_eq!(packed.len(), 1);
}
}