pub fn encode_bitfield(data: &mut [u8], bit_offset: usize, bit_length: usize, value: u16) {
let mask = if bit_length >= 16 {
0xFFFF
} else {
(1u16 << bit_length) - 1
};
let masked_value = value & mask;
for i in 0..bit_length {
let bit_pos = bit_offset + i;
let byte_idx = bit_pos / 8;
let bit_in_byte = bit_pos % 8;
if byte_idx >= data.len() {
panic!(
"Bitfield encoding exceeds buffer size: trying to write bit {} (byte {}), but buffer is only {} bytes. \
Field spans bits {}..{}, requiring {} bytes total.",
bit_pos,
byte_idx,
data.len(),
bit_offset,
bit_offset + bit_length,
(bit_offset + bit_length).div_ceil(8)
);
}
if (masked_value >> i) & 1 == 1 {
data[byte_idx] |= 1 << bit_in_byte;
} else {
data[byte_idx] &= !(1 << bit_in_byte);
}
}
}
pub fn decode_bitfield(data: &[u8], bit_offset: usize, bit_length: usize) -> u16 {
let mut value = 0u16;
for i in 0..bit_length {
let bit_pos = bit_offset + i;
let byte_idx = bit_pos / 8;
let bit_in_byte = bit_pos % 8;
if byte_idx < data.len() && (data[byte_idx] >> bit_in_byte) & 1 == 1 {
value |= 1 << i;
}
}
value
}
pub fn sign_extend(value: u16, bit_length: usize) -> i16 {
if bit_length == 0 || bit_length > 16 {
return value as i16;
}
if bit_length == 16 {
return value as i16;
}
let sign_bit = 1u16 << (bit_length - 1);
if value & sign_bit != 0 {
let extension_mask = !((1u16 << bit_length) - 1);
(value | extension_mask) as i16
} else {
value as i16
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_encode_decode_single_byte() {
let mut data = [0u8; 8];
encode_bitfield(&mut data, 0, 8, 0xAB);
assert_eq!(decode_bitfield(&data, 0, 8), 0xAB);
}
#[test]
fn test_encode_decode_across_boundary() {
let mut data = [0u8; 8];
encode_bitfield(&mut data, 6, 10, 0x3FF);
assert_eq!(decode_bitfield(&data, 6, 10), 0x3FF);
}
#[test]
fn test_sign_extend_positive() {
assert_eq!(sign_extend(0b0_1111_1111, 10), 255);
}
#[test]
fn test_sign_extend_negative() {
assert_eq!(sign_extend(0b11_1111_1111, 10), -1);
assert_eq!(sign_extend(0b10_0000_0000, 10), -512);
}
#[test]
fn test_encode_bitfield_single_bit() {
let mut data = [0u8; 4];
encode_bitfield(&mut data, 0, 1, 1);
assert_eq!(data[0], 0b00000001);
encode_bitfield(&mut data, 7, 1, 1);
assert_eq!(data[0], 0b10000001);
encode_bitfield(&mut data, 0, 1, 0);
assert_eq!(data[0], 0b10000000);
}
#[test]
fn test_encode_bitfield_nibbles() {
let mut data = [0u8; 4];
encode_bitfield(&mut data, 0, 4, 0xA);
assert_eq!(data[0], 0x0A);
encode_bitfield(&mut data, 4, 4, 0x5);
assert_eq!(data[0], 0x5A);
encode_bitfield(&mut data, 0, 4, 0xF);
assert_eq!(data[0], 0x5F);
}
#[test]
fn test_encode_bitfield_value_masking() {
let mut data = [0u8; 4];
encode_bitfield(&mut data, 0, 4, 0xFF); assert_eq!(data[0], 0x0F);
encode_bitfield(&mut data, 0, 8, 0x1234); assert_eq!(data[0], 0x34);
}
#[test]
fn test_encode_bitfield_cross_byte_boundary() {
let mut data = [0u8; 4];
encode_bitfield(&mut data, 4, 12, 0xFFF);
let decoded = decode_bitfield(&data, 4, 12);
assert_eq!(decoded, 0xFFF);
}
#[test]
fn test_encode_bitfield_multiple_values() {
let mut data = [0u8; 8];
encode_bitfield(&mut data, 0, 3, 0x5); encode_bitfield(&mut data, 3, 5, 0x1A); encode_bitfield(&mut data, 8, 4, 0xC); encode_bitfield(&mut data, 12, 4, 0x3);
assert_eq!(data[0], 0b11010101); assert_eq!(data[1], 0b00111100); }
#[test]
fn test_encode_bitfield_edge_case_16_bits() {
let mut data = [0u8; 4];
encode_bitfield(&mut data, 0, 16, 0xFFFF);
assert_eq!(data[0], 0xFF);
assert_eq!(data[1], 0xFF);
data.fill(0);
encode_bitfield(&mut data, 8, 16, 0x1234);
assert_eq!(data[1], 0x34);
assert_eq!(data[2], 0x12);
}
#[test]
fn test_encode_bitfield_overwrite_existing() {
let mut data = [0xFF; 4];
encode_bitfield(&mut data, 0, 4, 0x0);
assert_eq!(data[0], 0xF0);
encode_bitfield(&mut data, 4, 4, 0x5);
assert_eq!(data[0], 0x50);
}
#[test]
fn test_decode_bitfield_single_bit() {
let data = [0b10000001, 0x00, 0x00, 0x00];
assert_eq!(decode_bitfield(&data, 0, 1), 1); assert_eq!(decode_bitfield(&data, 1, 1), 0); assert_eq!(decode_bitfield(&data, 7, 1), 1); }
#[test]
fn test_decode_bitfield_out_of_bounds() {
let data = [0xFF];
assert_eq!(decode_bitfield(&data, 4, 8), 0x0F);
assert_eq!(decode_bitfield(&data, 8, 8), 0x00);
}
#[test]
fn test_decode_bitfield_zero_length() {
let data = [0xFF, 0xFF, 0xFF, 0xFF];
assert_eq!(decode_bitfield(&data, 0, 0), 0);
assert_eq!(decode_bitfield(&data, 10, 0), 0);
}
#[test]
fn test_decode_bitfield_16_bits() {
let data = [0x34, 0x12, 0x00, 0x00];
assert_eq!(decode_bitfield(&data, 0, 16), 0x1234);
}
#[test]
fn test_decode_bitfield_sparse_bits() {
let data = [0b10101010, 0x00, 0x00, 0x00];
assert_eq!(decode_bitfield(&data, 0, 2), 0b10); assert_eq!(decode_bitfield(&data, 2, 2), 0b10); assert_eq!(decode_bitfield(&data, 4, 2), 0b10); assert_eq!(decode_bitfield(&data, 6, 2), 0b10); }
#[test]
fn test_sign_extend_various_bit_lengths() {
assert_eq!(sign_extend(0x0, 1), 0);
assert_eq!(sign_extend(0x1, 1), -1);
assert_eq!(sign_extend(0x0, 2), 0);
assert_eq!(sign_extend(0x1, 2), 1);
assert_eq!(sign_extend(0x2, 2), -2);
assert_eq!(sign_extend(0x3, 2), -1);
assert_eq!(sign_extend(0x3, 3), 3); assert_eq!(sign_extend(0x4, 3), -4); assert_eq!(sign_extend(0x7, 3), -1); }
#[test]
fn test_sign_extend_8_bit() {
assert_eq!(sign_extend(0x00, 8), 0);
assert_eq!(sign_extend(0x7F, 8), 127); assert_eq!(sign_extend(0x80, 8), -128); assert_eq!(sign_extend(0xFF, 8), -1);
assert_eq!(sign_extend(0x01, 8), 1);
assert_eq!(sign_extend(0xFE, 8), -2);
}
#[test]
fn test_sign_extend_16_bit() {
assert_eq!(sign_extend(0x0000, 16), 0);
assert_eq!(sign_extend(0x7FFF, 16), 32767);
assert_eq!(sign_extend(0x8000, 16), -32768);
assert_eq!(sign_extend(0xFFFF, 16), -1);
}
#[test]
fn test_sign_extend_edge_cases() {
assert_eq!(sign_extend(0x1234, 0), 0x1234_u16 as i16);
assert_eq!(sign_extend(0x1234, 17), 0x1234_u16 as i16);
assert_eq!(sign_extend(0x1234, 32), 0x1234_u16 as i16);
}
#[test]
fn test_sign_extend_j1939_common_sizes() {
assert_eq!(sign_extend(0x000, 12), 0); assert_eq!(sign_extend(0x7FF, 12), 2047); assert_eq!(sign_extend(0x800, 12), -2048); assert_eq!(sign_extend(0xFFF, 12), -1);
assert_eq!(sign_extend(0x0FFF, 13), 4095);
assert_eq!(sign_extend(0x1000, 13), -4096);
assert_eq!(sign_extend(0x1FFF, 14), 8191);
assert_eq!(sign_extend(0x2000, 14), -8192);
}
#[test]
fn test_encode_decode_roundtrip_signed() {
let mut data = [0u8; 8];
let test_values = [-128i16, -1, 0, 1, 127];
for &value in &test_values {
data.fill(0);
let unsigned_value = value as u16;
encode_bitfield(&mut data, 0, 8, unsigned_value);
let decoded = decode_bitfield(&data, 0, 8);
let sign_extended = sign_extend(decoded, 8);
assert_eq!(sign_extended, value, "Failed roundtrip for value {}", value);
}
}
#[test]
fn test_encode_decode_roundtrip_12_bit_signed() {
let mut data = [0u8; 8];
let test_values = [-2048i16, -1, 0, 1, 2047];
for &value in &test_values {
data.fill(0);
let unsigned_value = value as u16;
encode_bitfield(&mut data, 4, 12, unsigned_value); let decoded = decode_bitfield(&data, 4, 12);
let sign_extended = sign_extend(decoded, 12);
assert_eq!(
sign_extended, value,
"Failed 12-bit roundtrip for value {}",
value
);
}
}
}