This commit is contained in:
Carl Lerche
2017-03-13 15:13:44 -07:00
parent 73706494ef
commit 1deac1f16e
6 changed files with 5221 additions and 21515 deletions

View File

@@ -1,5 +0,0 @@
pub struct HuffmanState {
pub next: usize,
pub byte: u8,
pub flags: u8,
}

119
src/hpack/huffman/mod.rs Normal file
View File

@@ -0,0 +1,119 @@
mod table;
use self::table::DECODE_TABLE;
use hpack::DecoderError;
use bytes::{BytesMut, BufMut};
// Constructed in the generated `table.rs` file
struct Decoder {
state: usize,
maybe_eos: bool,
}
// These flags must match the ones in genhuff.rs
const MAYBE_EOS: u8 = 1;
const DECODED: u8 = 2;
const ERROR: u8 = 4;
pub fn decode(src: &[u8]) -> Result<BytesMut, DecoderError> {
let mut decoder = Decoder::new();
// Max compression ration is >= 0.5
let mut dst = BytesMut::with_capacity(src.len() << 1);
for b in src {
if let Some(b) = try!(decoder.decode4(b >> 4)) {
dst.put_u8(b);
}
if let Some(b) = try!(decoder.decode4(b & 0xf)) {
dst.put_u8(b);
}
}
if !decoder.maybe_eos {
// TODO: handle error
unimplemented!();
}
Ok(dst)
}
impl Decoder {
fn new() -> Decoder {
Decoder {
state: 0,
maybe_eos: false,
}
}
// Decodes 4 bits
fn decode4(&mut self, input: u8) -> Result<Option<u8>, DecoderError> {
// (next-state, byte, flags)
let (next, byte, flags) = DECODE_TABLE[self.state][input as usize];
if flags & ERROR == ERROR {
// Data followed the EOS marker
unimplemented!();
}
let mut ret = None;
if flags & DECODED == DECODED {
ret = Some(byte);
}
self.state = next;
self.maybe_eos = flags & MAYBE_EOS == MAYBE_EOS;
Ok(ret)
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn decode_single_byte() {
let buf = [0b00111111];
let actual = decode(&buf).unwrap();
assert_eq!(actual, "o");
/*
let mut decoder = HuffmanDecoder::new();
// (The + (2^n - 1) at the final byte is to add the correct expected
// padding: 1s)
{
// We need to shift it by 3, since we need the top-order bytes to
// start the code point.
let hex_buffer = [(0x7 << 3) + 7];
let expected_result = vec![b'o'];
let result = decoder.decode(&hex_buffer).ok().unwrap();
assert_eq!(result, expected_result);
}
{
let hex_buffer = [0x0 + 7];
let expected_result = vec![b'0'];
let result = decoder.decode(&hex_buffer).ok().unwrap();
assert_eq!(result, expected_result);
}
{
// The length of the codepoint is 6, so we shift by two
let hex_buffer = [(0x21 << 2) + 3];
let expected_result = vec![b'A'];
let result = decoder.decode(&hex_buffer).ok().unwrap();
assert_eq!(result, expected_result);
}
*/
}
}

4869
src/hpack/huffman/table.rs Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -2,10 +2,9 @@ mod encoder;
mod decoder;
mod entry;
mod huffman;
mod huffman_table;
// mod table;
pub use self::encoder::Encoder;
pub use self::entry::Entry;
pub use self::decoder::Decoder;
pub use self::decoder::{Decoder, DecoderError};
// pub use self::table::Entry;