use crate::error::{BitUtilsError, Result};
pub fn u64_to_bits_be(val: u64, bits_len: usize) -> Result<Vec<u8>> {
if val != 0 && bits_len < 64 && (val >> bits_len) != 0 {
return Err(BitUtilsError::ValueOverflow {
value: val,
bits: bits_len,
}
.into());
}
let mut bits = Vec::with_capacity(bits_len);
for i in (0..bits_len).rev() {
let bit = if i < 64 { (val >> i) & 1 } else { 0 };
bits.push(bit as u8);
}
Ok(bits)
}
pub fn bits_to_u64_be(bits: &[u8]) -> u64 {
bits.iter()
.fold(0u64, |acc, &bit| (acc << 1) | (bit as u64 & 1))
}
pub fn bits_to_bytes_be(bits: &[u8]) -> Vec<u8> {
bits.chunks(8)
.map(|chunk| {
chunk
.iter()
.enumerate()
.fold(0u8, |acc, (i, &bit)| acc | (bit << (7 - i)))
})
.collect()
}
pub fn bytes_to_bits_be(bytes: &[u8]) -> Vec<u8> {
let mut bits = Vec::with_capacity(bytes.len() * 8);
for &byte in bytes {
for i in (0..8).rev() {
bits.push((byte >> i) & 1);
}
}
bits
}
#[cfg(test)]
mod tests {
use super::*;
use crate::error::{MatterPayloadError, BitUtilsError};
#[test]
fn test_u64_to_bits_be() {
assert_eq!(u64_to_bits_be(0b1011, 4).unwrap(), vec![1, 0, 1, 1]);
assert_eq!(u64_to_bits_be(0b1011, 8).unwrap(), vec![0, 0, 0, 0, 1, 0, 1, 1]);
assert_eq!(u64_to_bits_be(0, 4).unwrap(), vec![0, 0, 0, 0]);
assert_eq!(u64_to_bits_be(u64::MAX, 64).unwrap().len(), 64);
}
#[test]
fn test_u64_to_bits_overflow() {
let result = u64_to_bits_be(16, 4); let expected = MatterPayloadError::BitUtils(BitUtilsError::ValueOverflow {
value: 16,
bits: 4,
});
assert_eq!(result.unwrap_err(), expected);
assert!(u64_to_bits_be(0, 1).is_ok());
assert!(u64_to_bits_be(15, 4).is_ok());
}
#[test]
fn test_bits_to_u64_be() {
assert_eq!(bits_to_u64_be(&[1, 0, 1, 1]), 11);
assert_eq!(bits_to_u64_be(&[0, 0, 0, 0, 1, 0, 1, 1]), 11);
assert_eq!(bits_to_u64_be(&[0]), 0);
assert_eq!(bits_to_u64_be(&[]), 0);
}
#[test]
fn test_pack_unpack_roundtrip() {
let original_bits = vec![1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0]; let bytes = bits_to_bytes_be(&original_bits);
assert_eq!(bytes, vec![0b10110101, 0b11100000]);
let unpacked_bits = bytes_to_bits_be(&bytes);
assert_eq!(&unpacked_bits[..original_bits.len()], &original_bits[..]);
}
#[test]
fn test_full_byte_packing() {
let bits = vec![1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0];
let bytes = bits_to_bytes_be(&bits);
assert_eq!(bytes, vec![0xFF, 0x00]);
let unpacked = bytes_to_bits_be(&bytes);
assert_eq!(unpacked, bits);
}
#[test]
fn test_empty_inputs() {
assert_eq!(u64_to_bits_be(0, 0).unwrap(), Vec::<u8>::new());
assert!(u64_to_bits_be(1, 0).is_err());
assert_eq!(bits_to_u64_be(&[]), 0);
assert_eq!(bits_to_bytes_be(&[]), Vec::<u8>::new());
assert_eq!(bytes_to_bits_be(&[]), Vec::<u8>::new());
}
}