1
0
Fork 0
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:
Robin Appelman 2019-02-16 18:05:32 +01:00
commit 74124393be
2 changed files with 89 additions and 16 deletions

View file

@ -2,6 +2,7 @@
extern crate test; extern crate test;
use std::cmp::min;
use std::mem::size_of; use std::mem::size_of;
#[cfg(test)] #[cfg(test)]
@ -76,7 +77,7 @@ impl<'a> BitBuffer<'a> {
pub fn read_usize(&self, position: usize, count: usize) -> usize { pub fn read_usize(&self, position: usize, count: usize) -> usize {
let byte_index = position / 8; let byte_index = position / 8;
let bit_offset = position & 7; 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 { let container_le = unsafe {
std::mem::transmute::<[u8; USIZE_SIZE], usize>(*bytes) std::mem::transmute::<[u8; USIZE_SIZE], usize>(*bytes)
}; };
@ -86,6 +87,15 @@ impl<'a> BitBuffer<'a> {
shifted & mask 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 { pub fn read_u8(&self, position: usize, count: usize) -> u8 {
self.read_usize(position, count) as 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 { 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 self.read_usize(position, count) as u32
} else { } else {
let value:u32 = (self.read_u16(position, count) as u32) << 16; let value: u32 = self.read_u16(position, count) as u32;
value | self.read_u16(position + 16, count - 16) 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 { pub fn read_i8(&self, position: usize, count: usize) -> i8 {
let unsigned = self.read_u8(position, count); let unsigned = self.read_u8(position, count);
make_signed!(unsigned, i8, count) make_signed!(unsigned, i8, count)
@ -116,4 +148,21 @@ impl<'a> BitBuffer<'a> {
let unsigned = self.read_u32(position, count); let unsigned = self.read_u32(position, count);
make_signed!(unsigned, i32, 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
}
} }

View file

@ -2,22 +2,46 @@ use std::fs;
use super::*; use super::*;
use test::Bencher; 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(0, 1), 0b1);
assert_eq!(buffer.read_u8(1, 1), 0b0); assert_eq!(buffer.read_u8(1, 1), 0b0);
assert_eq!(buffer.read_u8(2, 2), 0b01); assert_eq!(buffer.read_u8(2, 2), 0b01);
assert_eq!(buffer.read_u8(7, 5), 0b10101); assert_eq!(buffer.read_u8(7, 5), 0b1010_1);
assert_eq!(buffer.read_u8(6, 5), 0b01010); assert_eq!(buffer.read_u8(6, 5), 0b010_10);
assert_eq!(buffer.read_u16(6, 12), 0b000110101010); }
#[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 { fn read_perf(buffer: BitBuffer) -> u16 {
@ -44,7 +68,7 @@ fn perf(b: &mut Bencher) {
b.iter(|| { b.iter(|| {
let buffer = BitBuffer::from_padded_slice(&bytes, length); let buffer = BitBuffer::from_padded_slice(&bytes, length);
let data = read_perf(buffer); let data = read_perf(buffer);
// assert_eq!(data, 43943); assert_eq!(data, 43943);
test::black_box(data); test::black_box(data);
}); });
} }