diff options
author | Paul Masurel <paul.masurel@gmail.com> | 2016-11-25 20:18:10 +0900 |
---|---|---|
committer | Paul Masurel <paul.masurel@gmail.com> | 2016-11-25 20:18:10 +0900 |
commit | 044880ea9bcec39a547e259b6285a1cfab0c4567 (patch) | |
tree | ce2e0f1cf4d7aa34a60e6efe2544a65d0076fbbb /src/common/bitpacker.rs | |
parent | b493051fe4e8aa6bfdf10fcd869864e10048c272 (diff) |
issue/55 working.
Diffstat (limited to 'src/common/bitpacker.rs')
-rw-r--r-- | src/common/bitpacker.rs | 57 |
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); |