summaryrefslogtreecommitdiffstats
path: root/src/common/bitpacker.rs
diff options
context:
space:
mode:
authorPaul Masurel <paul.masurel@gmail.com>2016-11-25 20:18:10 +0900
committerPaul Masurel <paul.masurel@gmail.com>2016-11-25 20:18:10 +0900
commit044880ea9bcec39a547e259b6285a1cfab0c4567 (patch)
treece2e0f1cf4d7aa34a60e6efe2544a65d0076fbbb /src/common/bitpacker.rs
parentb493051fe4e8aa6bfdf10fcd869864e10048c272 (diff)
issue/55 working.
Diffstat (limited to 'src/common/bitpacker.rs')
-rw-r--r--src/common/bitpacker.rs57
1 files changed, 30 insertions, 27 deletions
diff --git a/src/common/bitpacker.rs b/src/common/bitpacker.rs
index ca9e5e8..a99bc21 100644
--- a/src/common/bitpacker.rs
+++ b/src/common/bitpacker.rs
@@ -8,19 +8,17 @@ pub fn compute_num_bits(amplitude: u32) -> u8 {
(32u32 - amplitude.leading_zeros()) as u8
}
-pub struct BitPacker<TWrite: Write> {
- output: TWrite,
+pub struct BitPacker {
mini_buffer: u64,
mini_buffer_written: usize,
num_bits: usize,
written_size: usize,
}
-impl<TWrite: Write> BitPacker<TWrite> {
+impl BitPacker {
- pub fn new(output: TWrite, num_bits: usize) -> BitPacker<TWrite> {
+ pub fn new(num_bits: usize) -> BitPacker {
BitPacker {
- output: output,
mini_buffer: 0u64,
mini_buffer_written: 0,
num_bits: num_bits,
@@ -28,11 +26,11 @@ impl<TWrite: Write> BitPacker<TWrite> {
}
}
- pub fn write(&mut self, val: u32) -> io::Result<()> {
+ pub fn write<TWrite: Write>(&mut self, val: u32, output: &mut TWrite) -> io::Result<()> {
let val_u64 = val as u64;
if self.mini_buffer_written + self.num_bits > 64 {
self.mini_buffer |= val_u64.wrapping_shl(self.mini_buffer_written as u32);
- self.written_size += self.mini_buffer.serialize(&mut self.output)?;
+ self.written_size += self.mini_buffer.serialize(output)?;
self.mini_buffer = val_u64.wrapping_shr((64 - self.mini_buffer_written) as u32);
self.mini_buffer_written = self.mini_buffer_written + (self.num_bits as usize) - 64;
}
@@ -40,7 +38,7 @@ impl<TWrite: Write> BitPacker<TWrite> {
self.mini_buffer |= val_u64 << self.mini_buffer_written;
self.mini_buffer_written += self.num_bits;
if self.mini_buffer_written == 64 {
- self.written_size += self.mini_buffer.serialize(&mut self.output)?;
+ self.written_size += self.mini_buffer.serialize(output)?;
self.mini_buffer_written = 0;
self.mini_buffer = 0u64;
}
@@ -48,37 +46,39 @@ impl<TWrite: Write> BitPacker<TWrite> {
Ok(())
}
- fn flush(&mut self) -> io::Result<()>{
+ fn flush<TWrite: Write>(&mut self, output: &mut TWrite) -> io::Result<()>{
if self.mini_buffer_written > 0 {
let num_bytes = (self.mini_buffer_written + 7) / 8;
let arr: [u8; 8] = unsafe { mem::transmute::<u64, [u8; 8]>(self.mini_buffer) };
- self.output.write_all(&arr[..num_bytes])?;
+ output.write_all(&arr[..num_bytes])?;
self.written_size += num_bytes;
self.mini_buffer_written = 0;
}
Ok(())
}
- pub fn close(mut self) -> io::Result<(TWrite, usize)> {
- self.flush()?;
- Ok((self.output, self.written_size))
+ pub fn close<TWrite: Write>(&mut self, output: &mut TWrite) -> io::Result<usize> {
+ self.flush(output)?;
+ Ok(self.written_size)
}
}
-pub struct BitUnpacker<'a> {
- data: &'a [u8],
+pub struct BitUnpacker {
num_bits: usize,
mask: u32,
+ data_ptr: *const u8,
+ data_len: usize,
}
-impl<'a> BitUnpacker<'a> {
- pub fn new(data: &'a [u8], num_bits: usize) -> BitUnpacker<'a> {
+impl BitUnpacker {
+ pub fn new(data: &[u8], num_bits: usize) -> BitUnpacker {
BitUnpacker {
- data: data,
num_bits: num_bits,
mask: (1u32 << num_bits) - 1u32,
+ data_ptr: data.as_ptr(),
+ data_len: data.len()
}
}
@@ -87,15 +87,17 @@ impl<'a> BitUnpacker<'a> {
return 0;
}
let addr = (idx * self.num_bits) / 8;
- let bit_shift = (idx * self.num_bits) - addr * 8;
+ let bit_shift = idx * self.num_bits - addr * 8;
let val_unshifted_unmasked: u64;
- if addr + 8 <= self.data.len() {
- val_unshifted_unmasked = unsafe { * (self.data.as_ptr().offset(addr as isize) as *const u64) };
+ if addr + 8 <= self.data_len {
+ val_unshifted_unmasked = unsafe { * (self.data_ptr.offset(addr as isize) as *const u64) };
}
- else {
+ else {
let mut arr = [0u8; 8];
- for i in 0..self.data.len() - addr {
- arr[i] = self.data[addr + i];
+ if addr < self.data_len {
+ for i in 0..self.data_len - addr {
+ arr[i] = unsafe { *self.data_ptr.offset( (addr + i) as isize) };
+ }
}
val_unshifted_unmasked = unsafe { mem::transmute::<[u8; 8], u64>(arr) };
}
@@ -124,7 +126,8 @@ mod test {
}
fn test_bitpacker_util(len: usize, num_bits: usize) {
- let mut bitpacker = BitPacker::new(Vec::new(), num_bits);
+ let mut data = Vec::new();
+ let mut bitpacker = BitPacker::new(num_bits);
let max_val: u32 = (1 << num_bits) - 1;
let vals: Vec<u32> = (0u32..len as u32).map(|i| {
if max_val == 0 {
@@ -135,9 +138,9 @@ mod test {
}
}).collect();
for &val in &vals {
- bitpacker.write(val).unwrap();
+ bitpacker.write(val, &mut data).unwrap();
}
- let (data, num_bytes) = bitpacker.close().unwrap();
+ let num_bytes = bitpacker.close(&mut data).unwrap();
assert_eq!(num_bytes, (num_bits * len + 7) / 8);
assert_eq!(data.len(), num_bytes);
let bitunpacker = BitUnpacker::new(&data, num_bits);