mod reader;
mod writer;
pub use reader::BitReader;
pub use writer::BitWriter;
#[cfg(kani)]
mod kani_proofs {
use super::{BitReader, BitWriter};
const BUF_LEN: usize = 8;
#[kani::proof]
fn read_u64_never_panics() {
let data: [u8; 4] = kani::any();
let nbits: u32 = kani::any();
let mut r = BitReader::new(&data);
let _ = r.read_u64(nbits);
}
#[kani::proof]
#[kani::unwind(65)]
fn write_bits_never_panics() {
let mut buf: [u8; 4] = kani::any();
let value: u64 = kani::any();
let nbits: u32 = kani::any();
kani::assume(nbits <= 100);
let mut w = BitWriter::new(&mut buf);
let _ = w.write_bits(value, nbits);
}
#[kani::proof]
#[kani::unwind(65)]
fn write_read_u64_roundtrip() {
let nbits: u32 = kani::any();
kani::assume(nbits >= 1 && nbits <= 64);
let value: u64 = kani::any();
let masked = if nbits == 64 {
value
} else {
value & ((1u64 << nbits) - 1)
};
let mut buf = [0u8; BUF_LEN];
let mut w = BitWriter::new(&mut buf);
w.write_bits(masked, nbits).unwrap();
let mut r = BitReader::new(&buf);
assert_eq!(r.read_u64(nbits).unwrap(), masked);
}
}
#[cfg(test)]
mod proptests {
use proptest::prelude::*;
use super::{BitReader, BitWriter};
proptest! {
#[test]
fn read_u64_never_panics(data: [u8; 4], nbits: u32) {
let mut r = BitReader::new(&data);
let _ = r.read_u64(nbits);
}
#[test]
fn write_bits_never_panics(mut buf: [u8; 4], value: u64, nbits in 0u32..=100) {
let mut w = BitWriter::new(&mut buf);
let _ = w.write_bits(value, nbits);
}
#[test]
fn write_read_u64_roundtrip(nbits in 1u32..=64, value: u64) {
let masked = if nbits == 64 { value } else { value & ((1u64 << nbits) - 1) };
let mut buf = [0u8; 8];
let mut w = BitWriter::new(&mut buf);
w.write_bits(masked, nbits).unwrap();
let mut r = BitReader::new(&buf);
prop_assert_eq!(r.read_u64(nbits).unwrap(), masked);
}
}
}