mirror of
https://codeberg.org/icewind/bitbuffer.git
synced 2026-06-03 16:44:06 +02:00
bool and u64
This commit is contained in:
parent
f5aff2cd80
commit
74124393be
2 changed files with 89 additions and 16 deletions
57
src/lib.rs
57
src/lib.rs
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
extern crate test;
|
||||
|
||||
use std::cmp::min;
|
||||
use std::mem::size_of;
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
@ -76,7 +77,7 @@ impl<'a> BitBuffer<'a> {
|
|||
pub fn read_usize(&self, position: usize, count: usize) -> usize {
|
||||
let byte_index = position / 8;
|
||||
let bit_offset = position & 7;
|
||||
let bytes:&[u8; USIZE_SIZE] = array_ref!(self.bytes, byte_index, USIZE_SIZE);
|
||||
let bytes: &[u8; USIZE_SIZE] = array_ref!(self.bytes, byte_index, USIZE_SIZE);
|
||||
let container_le = unsafe {
|
||||
std::mem::transmute::<[u8; USIZE_SIZE], usize>(*bytes)
|
||||
};
|
||||
|
|
@ -86,6 +87,15 @@ impl<'a> BitBuffer<'a> {
|
|||
shifted & mask
|
||||
}
|
||||
|
||||
pub fn read_bool(&self, position: usize) -> bool {
|
||||
let byte_index = position / 8;
|
||||
let bit_offset = position & 7;
|
||||
let byte = self.bytes[byte_index];
|
||||
let shifted = byte >> bit_offset;
|
||||
let mask = 1u8 << bit_offset;
|
||||
shifted & mask == 1
|
||||
}
|
||||
|
||||
pub fn read_u8(&self, position: usize, count: usize) -> u8 {
|
||||
self.read_usize(position, count) as u8
|
||||
}
|
||||
|
|
@ -95,13 +105,35 @@ impl<'a> BitBuffer<'a> {
|
|||
}
|
||||
|
||||
pub fn read_u32(&self, position: usize, count: usize) -> u32 {
|
||||
if size_of::<usize>() > size_of::<u32>() {
|
||||
if size_of::<usize>() > size_of::<u32>() || (count / 8) < size_of::<usize>() {
|
||||
self.read_usize(position, count) as u32
|
||||
} else {
|
||||
let value:u32 = (self.read_u16(position, count) as u32) << 16;
|
||||
value | self.read_u16(position + 16, count - 16) as u32
|
||||
let value: u32 = self.read_u16(position, count) as u32;
|
||||
value | (self.read_u16(position + 16, count - 16) as u32) << 16
|
||||
}
|
||||
}
|
||||
|
||||
pub fn read_u64(&self, position: usize, count: usize) -> u64 {
|
||||
if size_of::<usize>() > size_of::<u64>() || (count / 8) < size_of::<usize>() {
|
||||
self.read_usize(position, count) as u64
|
||||
} else {
|
||||
let mut bits_left = count;
|
||||
let mut value = 0;
|
||||
let max_read = (size_of::<usize>() - 1) * 8;
|
||||
let mut read_pos = position;
|
||||
let mut bit_offset = 0;
|
||||
while bits_left > 0 {
|
||||
let read = min(bits_left, max_read);
|
||||
value |= (self.read_usize(read_pos, read) as u64) << bit_offset;
|
||||
bit_offset += read;
|
||||
read_pos += read;
|
||||
bits_left -= read;
|
||||
}
|
||||
|
||||
value
|
||||
}
|
||||
}
|
||||
|
||||
pub fn read_i8(&self, position: usize, count: usize) -> i8 {
|
||||
let unsigned = self.read_u8(position, count);
|
||||
make_signed!(unsigned, i8, count)
|
||||
|
|
@ -116,4 +148,21 @@ impl<'a> BitBuffer<'a> {
|
|||
let unsigned = self.read_u32(position, count);
|
||||
make_signed!(unsigned, i32, count)
|
||||
}
|
||||
|
||||
pub fn read_bytes(&self, position: usize, byte_count: usize) -> Vec<u8> {
|
||||
let mut data = vec!();
|
||||
data.reserve_exact(byte_count);
|
||||
let mut byte_left = byte_count;
|
||||
let max_read = size_of::<usize>() - 1;
|
||||
let mut read_pos = position;
|
||||
while byte_left > 0 {
|
||||
let read = min(byte_left, max_read);
|
||||
let bytes: [u8; USIZE_SIZE] = self.read_usize(read_pos, read * 8).to_le_bytes();
|
||||
let usable_bytes = &bytes[0..max_read];
|
||||
data.extend_from_slice(usable_bytes);
|
||||
byte_left -= read;
|
||||
read_pos += read;
|
||||
}
|
||||
data
|
||||
}
|
||||
}
|
||||
48
src/tests.rs
48
src/tests.rs
|
|
@ -2,22 +2,46 @@ use std::fs;
|
|||
use super::*;
|
||||
use test::Bencher;
|
||||
|
||||
#[test]
|
||||
fn read_le() {
|
||||
let bytes: &[u8] = &[
|
||||
0b1011_0101, 0b0110_1010, 0b1010_1100, 0b1001_1001,
|
||||
0b1001_1001, 0b1001_1001, 0b1001_1001, 0b1110_0111,
|
||||
0, 0, 0, 0, 0, 0, 0, 0
|
||||
];
|
||||
|
||||
let buffer = BitBuffer::from_padded_slice(&bytes, 8);
|
||||
const BYTES: &'static[u8] = &[
|
||||
0b1011_0101, 0b0110_1010, 0b1010_1100, 0b1001_1001,
|
||||
0b1001_1001, 0b1001_1001, 0b1001_1001, 0b1110_0111,
|
||||
0, 0, 0, 0, 0, 0, 0, 0
|
||||
];
|
||||
|
||||
#[test]
|
||||
fn read_u8() {
|
||||
let buffer = BitBuffer::from_padded_slice(BYTES, 8);
|
||||
|
||||
assert_eq!(buffer.read_u8(0, 1), 0b1);
|
||||
assert_eq!(buffer.read_u8(1, 1), 0b0);
|
||||
assert_eq!(buffer.read_u8(2, 2), 0b01);
|
||||
assert_eq!(buffer.read_u8(7, 5), 0b10101);
|
||||
assert_eq!(buffer.read_u8(6, 5), 0b01010);
|
||||
assert_eq!(buffer.read_u16(6, 12), 0b000110101010);
|
||||
assert_eq!(buffer.read_u8(7, 5), 0b1010_1);
|
||||
assert_eq!(buffer.read_u8(6, 5), 0b010_10);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn read_u16() {
|
||||
let buffer = BitBuffer::from_padded_slice(BYTES, 8);
|
||||
|
||||
assert_eq!(buffer.read_u16(6, 12), 0b00_0110_1010_10);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn read_u32() {
|
||||
let buffer = BitBuffer::from_padded_slice(BYTES, 8);
|
||||
|
||||
assert_eq!(buffer.read_u32(6, 24), 0b01_1001_1010_1100_0110_1010_10);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn read_u64() {
|
||||
let buffer = BitBuffer::from_padded_slice(BYTES, 8);
|
||||
|
||||
|
||||
println!("{:#036b}", buffer.read_u64(6, 32));
|
||||
assert_eq!(buffer.read_u64(6, 34), 0b1001_1001_1001_1001_1010_1100_0110_1010_10);
|
||||
assert_eq!(buffer.read_u64(6, 60), 0b00_1110_01111001_1001_1001_1001_1001_1001_1001_1001_1010_1100_0110_1010_10);
|
||||
}
|
||||
|
||||
fn read_perf(buffer: BitBuffer) -> u16 {
|
||||
|
|
@ -44,7 +68,7 @@ fn perf(b: &mut Bencher) {
|
|||
b.iter(|| {
|
||||
let buffer = BitBuffer::from_padded_slice(&bytes, length);
|
||||
let data = read_perf(buffer);
|
||||
// assert_eq!(data, 43943);
|
||||
assert_eq!(data, 43943);
|
||||
test::black_box(data);
|
||||
});
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue