extern crate byteorder;
use std::cmp;
use byteorder::{ByteOrder, LittleEndian};
mod tables;
mod cursor;
pub use cursor::DecodeCursor;
#[path="x86/x86.rs"]
pub mod x86;
pub trait Encoder {
fn encode_quads(input: &[u32], control_bytes: &mut [u8], output: &mut [u8]) -> (usize, usize);
}
pub trait Decoder {
fn decode_quads(control_bytes: &[u8], encoded_nums: &[u8], output: &mut [u32],
control_bytes_to_decode: usize) -> (usize, usize);
}
pub struct Scalar;
impl Encoder for Scalar {
fn encode_quads(input: &[u32], control_bytes: &mut [u8], encoded_nums: &mut [u8]) -> (usize, usize) {
let mut bytes_written = 0;
let mut nums_encoded = 0;
for quads_encoded in 0..control_bytes.len() {
let num0 = input[nums_encoded];
let num1 = input[nums_encoded + 1];
let num2 = input[nums_encoded + 2];
let num3 = input[nums_encoded + 3];
let len0 = encode_num_scalar(num0, &mut encoded_nums[bytes_written..]);
let len1 = encode_num_scalar(num1, &mut encoded_nums[bytes_written + len0..]);
let len2 = encode_num_scalar(num2, &mut encoded_nums[bytes_written + len0 + len1..]);
let len3 = encode_num_scalar(num3, &mut encoded_nums[bytes_written + len0 + len1 + len2..]);
control_bytes[quads_encoded] = ((len0 - 1) | (len1 - 1) << 2 | (len2 - 1) << 4 | (len3 - 1) << 6) as u8;
bytes_written += len0 + len1 + len2 + len3;
nums_encoded += 4;
}
(nums_encoded, bytes_written)
}
}
impl Decoder for Scalar {
fn decode_quads(control_bytes: &[u8], encoded_nums: &[u8], output: &mut [u32],
control_bytes_to_decode: usize) -> (usize, usize) {
debug_assert!(control_bytes_to_decode * 4 <= output.len());
let mut bytes_read: usize = 0;
let mut nums_decoded: usize = 0;
let control_byte_limit = cmp::min(control_bytes.len(), control_bytes_to_decode);
for &control_byte in control_bytes[0..control_byte_limit].iter() {
let (len0, len1, len2, len3) = tables::DECODE_LENGTH_PER_NUM_TABLE[control_byte as usize];
let len0 = len0 as usize;
let len1 = len1 as usize;
let len2 = len2 as usize;
let len3 = len3 as usize;
output[nums_decoded] = decode_num_scalar(len0, &encoded_nums[bytes_read..]);
output[nums_decoded + 1] = decode_num_scalar(len1, &encoded_nums[bytes_read + len0..]);
output[nums_decoded + 2] = decode_num_scalar(len2, &encoded_nums[bytes_read + len0 + len1..]);
output[nums_decoded + 3] = decode_num_scalar(len3, &encoded_nums[bytes_read + len0 + len1 + len2..]);
bytes_read += len0 + len1 + len2 + len3;
nums_decoded += 4;
}
(nums_decoded, bytes_read)
}
}
pub fn encode<E: Encoder>(input: &[u32], output: &mut [u8]) -> usize {
if input.len() == 0 {
return 0;
}
let shape = encoded_shape(input.len());
let (control_bytes, encoded_bytes) = output.split_at_mut(shape.control_bytes_len);
let (nums_encoded, mut num_bytes_written) = E::encode_quads(&input[..],
&mut control_bytes[0..shape.complete_control_bytes_len],
&mut encoded_bytes[..]);
let control_bytes_written = nums_encoded / 4;
let (more_nums_encoded, more_bytes_written) =
Scalar::encode_quads(&input[nums_encoded..],
&mut control_bytes[control_bytes_written..shape.complete_control_bytes_len],
&mut encoded_bytes[num_bytes_written..]);
num_bytes_written += more_bytes_written;
debug_assert_eq!(shape.complete_control_bytes_len * 4, nums_encoded + more_nums_encoded);
if shape.leftover_numbers > 0 {
let mut control_byte = 0;
let mut nums_encoded = shape.complete_control_bytes_len * 4;
for i in 0..shape.leftover_numbers {
let num = input[nums_encoded];
let len = encode_num_scalar(num, &mut encoded_bytes[num_bytes_written..]);
control_byte |= ((len - 1) as u8) << (i * 2);
num_bytes_written += len;
nums_encoded += 1;
}
control_bytes[shape.complete_control_bytes_len] = control_byte;
}
control_bytes.len() + num_bytes_written
}
pub fn decode<D: Decoder>(input: &[u8], count: usize, output: &mut [u32]) -> usize {
let mut cursor = DecodeCursor::new(&input, count);
assert_eq!(count, cursor.decode::<D>(output), "output buffer was not large enough");
cursor.input_consumed()
}
#[derive(Debug, PartialEq)]
struct EncodedShape {
control_bytes_len: usize,
complete_control_bytes_len: usize,
leftover_numbers: usize
}
fn encoded_shape(count: usize) -> EncodedShape {
EncodedShape {
control_bytes_len: (count + 3) / 4,
complete_control_bytes_len: count / 4,
leftover_numbers: count % 4
}
}
fn encode_num_scalar(num: u32, output: &mut [u8]) -> usize {
let len = cmp::max(1_usize, 4 - num.leading_zeros() as usize / 8);
let mut buf = [0_u8; 4];
LittleEndian::write_u32(&mut buf, num);
for i in 0..len {
output[i] = buf[i];
}
len
}
fn decode_num_scalar(len: usize, input: &[u8]) -> u32 {
let mut buf = [0_u8; 4];
&buf[0..len].copy_from_slice(&input[0..len]);
LittleEndian::read_u32(&buf)
}
fn cumulative_encoded_len(control_bytes: &[u8]) -> usize {
control_bytes.iter()
.map({ |&b| tables::DECODE_LENGTH_PER_QUAD_TABLE[b as usize] as usize })
.sum()
}
#[cfg(test)]
mod tests;