mirror of
https://codeberg.org/icewind/bitbuffer.git
synced 2026-06-03 16:44:06 +02:00
317 lines
9.5 KiB
Rust
317 lines
9.5 KiB
Rust
use bitbuffer::num_traits::{IsSigned, SplitFitUsize, UncheckedPrimitiveInt};
|
|
use bitbuffer::{BigEndian, BitReadBuffer, BitReadStream, BitWriteStream, LittleEndian};
|
|
use num_traits::{PrimInt, WrappingSub};
|
|
use std::any::type_name;
|
|
use std::fmt::Debug;
|
|
use std::mem::size_of;
|
|
use std::ops::BitOrAssign;
|
|
use std::rc::Rc;
|
|
use std::sync::Arc;
|
|
|
|
#[test]
|
|
fn test_write_bool_le() {
|
|
let mut data = Vec::new();
|
|
{
|
|
let mut stream = BitWriteStream::new(&mut data, LittleEndian);
|
|
|
|
stream.write_bool(true).unwrap();
|
|
stream.write_bool(true).unwrap();
|
|
stream.write_bool(false).unwrap();
|
|
stream.write_bool(true).unwrap();
|
|
}
|
|
|
|
let mut read = BitReadStream::from(BitReadBuffer::new(&data, LittleEndian));
|
|
|
|
assert!(read.read_bool().unwrap());
|
|
assert!(read.read_bool().unwrap());
|
|
assert!(!read.read_bool().unwrap());
|
|
assert!(read.read_bool().unwrap());
|
|
|
|
// 0 padded
|
|
assert!(!read.read_bool().unwrap());
|
|
}
|
|
|
|
#[test]
|
|
fn test_write_bool_be() {
|
|
let mut data = Vec::new();
|
|
{
|
|
let mut stream = BitWriteStream::new(&mut data, BigEndian);
|
|
|
|
stream.write_bool(true).unwrap();
|
|
stream.write_bool(true).unwrap();
|
|
stream.write_bool(false).unwrap();
|
|
stream.write_bool(true).unwrap();
|
|
}
|
|
|
|
let mut read = BitReadStream::from(BitReadBuffer::new(&data, BigEndian));
|
|
|
|
assert!(read.read_bool().unwrap());
|
|
assert!(read.read_bool().unwrap());
|
|
assert!(!read.read_bool().unwrap());
|
|
assert!(read.read_bool().unwrap());
|
|
|
|
// 0 padded
|
|
assert!(!read.read_bool().unwrap());
|
|
}
|
|
|
|
#[test]
|
|
fn test_write_bool_number_le() {
|
|
let mut data = Vec::new();
|
|
{
|
|
let mut stream = BitWriteStream::new(&mut data, LittleEndian);
|
|
|
|
stream.write_bool(true).unwrap();
|
|
stream.write_int(3253u16, 16).unwrap();
|
|
stream.write_int(13253u64, 64).unwrap();
|
|
}
|
|
|
|
let mut read = BitReadStream::from(BitReadBuffer::new(&data, LittleEndian));
|
|
|
|
assert!(read.read_bool().unwrap());
|
|
assert_eq!(3253u16, read.read::<u16>().unwrap());
|
|
assert_eq!(13253u64, read.read::<u64>().unwrap());
|
|
|
|
// 0 padded
|
|
assert!(!read.read_bool().unwrap());
|
|
}
|
|
|
|
#[test]
|
|
fn test_write_bool_number_be() {
|
|
let mut data = Vec::new();
|
|
{
|
|
let mut stream = BitWriteStream::new(&mut data, BigEndian);
|
|
|
|
stream.write_bool(true).unwrap();
|
|
stream.write_int(3253u16, 16).unwrap();
|
|
stream.write_int(13253u64, 64).unwrap();
|
|
}
|
|
|
|
let mut read = BitReadStream::from(BitReadBuffer::new(&data, BigEndian));
|
|
|
|
assert_eq!(1u8, read.read_int::<u8>(1).unwrap());
|
|
assert_eq!(3253u16, read.read::<u16>().unwrap());
|
|
assert_eq!(13253u64, read.read::<u64>().unwrap());
|
|
|
|
// 0 padded
|
|
assert!(!read.read_bool().unwrap());
|
|
}
|
|
|
|
#[test]
|
|
fn test_write_float_le() {
|
|
let mut data = Vec::new();
|
|
{
|
|
let mut stream = BitWriteStream::new(&mut data, LittleEndian);
|
|
|
|
stream.write_bool(true).unwrap();
|
|
stream.write_float(3253.12f32).unwrap();
|
|
}
|
|
|
|
let mut read = BitReadStream::from(BitReadBuffer::new(&data, LittleEndian));
|
|
|
|
assert!(read.read_bool().unwrap());
|
|
assert_eq!(3253.12f32, read.read::<f32>().unwrap());
|
|
|
|
// 0 padded
|
|
assert!(!read.read_bool().unwrap());
|
|
}
|
|
|
|
#[test]
|
|
fn test_write_float_be() {
|
|
let mut data = Vec::new();
|
|
{
|
|
let mut stream = BitWriteStream::new(&mut data, BigEndian);
|
|
|
|
stream.write_bool(true).unwrap();
|
|
stream.write_float(3253.12f32).unwrap();
|
|
}
|
|
|
|
let mut read = BitReadStream::from(BitReadBuffer::new(&data, BigEndian));
|
|
|
|
assert_eq!(1u8, read.read_int::<u8>(1).unwrap());
|
|
assert_eq!(3253.12f32, read.read::<f32>().unwrap());
|
|
|
|
// 0 padded
|
|
assert!(!read.read_bool().unwrap());
|
|
}
|
|
|
|
#[test]
|
|
fn test_write_string_le() {
|
|
let mut data = Vec::new();
|
|
{
|
|
let mut stream = BitWriteStream::new(&mut data, LittleEndian);
|
|
|
|
stream.write_string("null terminated", None).unwrap();
|
|
stream.write_string("fixed length1", Some(16)).unwrap();
|
|
stream.write_string("fixed length2", Some(16)).unwrap();
|
|
}
|
|
|
|
let mut read = BitReadStream::from(BitReadBuffer::new(&data, LittleEndian));
|
|
|
|
assert_eq!("null terminated", read.read_string(None).unwrap());
|
|
assert_eq!("fixed length1", read.read_string(Some(16)).unwrap());
|
|
assert_eq!("fixed length2", read.read_string(Some(16)).unwrap());
|
|
}
|
|
|
|
#[test]
|
|
fn test_write_string_le_unaligned() {
|
|
let mut data = Vec::new();
|
|
{
|
|
let mut stream = BitWriteStream::new(&mut data, LittleEndian);
|
|
|
|
stream.write_bool(true).unwrap();
|
|
stream.write_string("null terminated", None).unwrap();
|
|
stream.write_string("fixed length1", Some(16)).unwrap();
|
|
stream.write_string("fixed length2", Some(16)).unwrap();
|
|
}
|
|
|
|
let mut read = BitReadStream::from(BitReadBuffer::new(&data, LittleEndian));
|
|
|
|
assert!(read.read_bool().unwrap());
|
|
assert_eq!("null terminated", read.read_string(None).unwrap());
|
|
assert_eq!("fixed length1", read.read_string(Some(16)).unwrap());
|
|
assert_eq!("fixed length2", read.read_string(Some(16)).unwrap());
|
|
|
|
// 0 padded
|
|
assert!(!read.read_bool().unwrap());
|
|
}
|
|
|
|
#[test]
|
|
fn test_write_signed() {
|
|
let mut data = Vec::new();
|
|
{
|
|
let mut stream = BitWriteStream::new(&mut data, LittleEndian);
|
|
|
|
stream.write_bool(true).unwrap();
|
|
stream.write_int(-17i32, 32).unwrap();
|
|
stream.write_int(-9i32, 8).unwrap();
|
|
}
|
|
|
|
let mut read = BitReadStream::from(BitReadBuffer::new(&data, LittleEndian));
|
|
|
|
assert!(read.read_bool().unwrap());
|
|
assert_eq!(-17i32, read.read_int::<i32>(32).unwrap());
|
|
assert_eq!(-9i32, read.read_int::<i32>(8).unwrap());
|
|
}
|
|
|
|
#[test]
|
|
fn test_write_container() {
|
|
let mut data = Vec::new();
|
|
{
|
|
let mut stream = BitWriteStream::new(&mut data, LittleEndian);
|
|
|
|
stream.write(&Box::new(true)).unwrap();
|
|
stream.write(&Rc::new(true)).unwrap();
|
|
stream.write(&Arc::new(true)).unwrap();
|
|
}
|
|
|
|
let mut read = BitReadStream::from(BitReadBuffer::new(&data, LittleEndian));
|
|
|
|
assert_eq!(Box::new(true), read.read().unwrap());
|
|
assert_eq!(Rc::new(true), read.read().unwrap());
|
|
assert_eq!(Arc::new(true), read.read().unwrap());
|
|
}
|
|
|
|
#[test]
|
|
fn test_write_to_slice() {
|
|
let mut data = [0; 32];
|
|
{
|
|
let mut stream = BitWriteStream::from_slice(&mut data[..], LittleEndian);
|
|
|
|
stream.write_bool(true).unwrap();
|
|
stream.write_int(3253u16, 16).unwrap();
|
|
stream.write_int(13253u64, 64).unwrap();
|
|
}
|
|
|
|
let mut read = BitReadStream::from(BitReadBuffer::new(&data[..], LittleEndian));
|
|
|
|
assert!(read.read_bool().unwrap());
|
|
assert_eq!(3253u16, read.read::<u16>().unwrap());
|
|
assert_eq!(13253u64, read.read::<u64>().unwrap());
|
|
|
|
// 0 padded
|
|
assert!(!read.read_bool().unwrap());
|
|
}
|
|
|
|
#[test]
|
|
fn test_write_last_slice() {
|
|
let mut data = [0; 1];
|
|
{
|
|
let mut stream = BitWriteStream::from_slice(&mut data[..], LittleEndian);
|
|
|
|
stream.write_int::<u8>(0b1000, 4).unwrap();
|
|
stream.write_bool(true).unwrap();
|
|
}
|
|
|
|
let mut read = BitReadStream::from(BitReadBuffer::new(&data[..], LittleEndian));
|
|
|
|
assert_eq!(0b1000, read.read_int::<u8>(4).unwrap());
|
|
assert!(read.read_bool().unwrap());
|
|
}
|
|
|
|
#[test]
|
|
fn test_write_be_long() {
|
|
let mut bytes = vec![];
|
|
let mut writer = BitWriteStream::new(&mut bytes, BigEndian);
|
|
let num1 = 0b11000_00111110u64;
|
|
let num2 = 0b1111111_11100100_00100100_11011101_00000011_11100000_01100111_11011011u64;
|
|
writer.write_int(num1, 13).unwrap();
|
|
writer.write_int(num2, 63).unwrap();
|
|
|
|
let buffer = BitReadBuffer::new(&bytes, BigEndian);
|
|
let mut reader = BitReadStream::new(buffer);
|
|
let num1actual = reader.read_int::<u64>(13).unwrap();
|
|
let num2actual = reader.read_int::<u64>(63).unwrap();
|
|
|
|
assert_eq!(num1actual, num1);
|
|
assert_eq!(num2actual, num2);
|
|
}
|
|
|
|
#[test]
|
|
fn test_write_all_lengths() {
|
|
let pattern = 0b10101010u8;
|
|
test_write_all_lengths_ty::<u8>(pattern);
|
|
test_write_all_lengths_ty::<u16>(u16::from_le_bytes([pattern; 2]));
|
|
test_write_all_lengths_ty::<u32>(u32::from_le_bytes([pattern; 4]));
|
|
test_write_all_lengths_ty::<u64>(u64::from_le_bytes([pattern; 8]));
|
|
test_write_all_lengths_ty::<u128>(u128::from_le_bytes([pattern; 16]));
|
|
test_write_all_lengths_ty::<usize>(usize::from_le_bytes([pattern; size_of::<usize>()]));
|
|
|
|
test_write_all_lengths_ty::<i8>(i8::from_le_bytes([pattern; 1]));
|
|
test_write_all_lengths_ty::<i16>(i16::from_le_bytes([pattern; 2]));
|
|
test_write_all_lengths_ty::<i32>(i32::from_le_bytes([pattern; 4]));
|
|
test_write_all_lengths_ty::<i64>(i64::from_le_bytes([pattern; 8]));
|
|
test_write_all_lengths_ty::<i128>(i128::from_le_bytes([pattern; 16]));
|
|
test_write_all_lengths_ty::<isize>(isize::from_le_bytes([pattern; size_of::<isize>()]));
|
|
}
|
|
|
|
fn test_write_all_lengths_ty<
|
|
T: PrimInt + BitOrAssign + IsSigned + UncheckedPrimitiveInt + Debug + SplitFitUsize + WrappingSub,
|
|
>(
|
|
pattern: T,
|
|
) {
|
|
let max_bits = size_of::<T>() * 8;
|
|
let mut bytes = Vec::new();
|
|
let mut writer = BitWriteStream::new(&mut bytes, BigEndian);
|
|
|
|
let mut expected = Vec::<T>::new();
|
|
|
|
for bits in 1..max_bits {
|
|
let value = pattern >> (max_bits - bits);
|
|
expected.push(value);
|
|
writer.write_int(value, bits).unwrap();
|
|
}
|
|
|
|
let buffer = BitReadBuffer::new(&bytes, BigEndian);
|
|
let mut reader = BitReadStream::new(buffer);
|
|
|
|
for (bits, expected_value) in (1..max_bits).zip(expected.into_iter()) {
|
|
let actual = reader.read_int::<T>(bits).unwrap();
|
|
assert_eq!(
|
|
expected_value,
|
|
actual,
|
|
"write + read for {} bits {}",
|
|
bits,
|
|
type_name::<T>()
|
|
);
|
|
}
|
|
}
|