|
|
@@ -9,27 +9,27 @@ use std::cmp::Ordering; |
|
|
|
#[derive(Error, Debug)] |
|
|
|
pub enum Err { |
|
|
|
#[error("Bad stream block type")] |
|
|
|
BSTyp, |
|
|
|
BlockType, |
|
|
|
#[error("Not enough bits for block")] |
|
|
|
Block, |
|
|
|
BlockBits, |
|
|
|
#[error("Not enough bits for 0-repeat")] |
|
|
|
Code0, |
|
|
|
Bits0, |
|
|
|
#[error("Not enough bits for code-repeat")] |
|
|
|
CodeC, |
|
|
|
BitsCode, |
|
|
|
#[error("Invalid alphabet index")] |
|
|
|
CodeN, |
|
|
|
AlphaIndex, |
|
|
|
#[error("Couldn't decode from table")] |
|
|
|
Decod, |
|
|
|
TableDecode, |
|
|
|
#[error("Bad distance in pair")] |
|
|
|
Distn, |
|
|
|
Distance, |
|
|
|
#[error("Couldn't read header for dynamic stream")] |
|
|
|
DyStr, |
|
|
|
DynStream, |
|
|
|
#[error("Couldn't decode length/distance pair")] |
|
|
|
Fixed, |
|
|
|
Pair, |
|
|
|
#[error("Not enough bytes for literal")] |
|
|
|
Liter, |
|
|
|
Literal, |
|
|
|
#[error("Bad symbol in alphabet")] |
|
|
|
Symbl, |
|
|
|
Symbol, |
|
|
|
#[error("Couldn't read table")] |
|
|
|
Table, |
|
|
|
} |
|
|
@@ -101,19 +101,19 @@ pub fn read_gzip(b: &[u8]) -> Option<&[u8]> { |
|
|
|
/// # Errors |
|
|
|
/// |
|
|
|
/// Returns `Err` if the bit-stream fails to parse. |
|
|
|
pub fn read(b: &[u8], p: &mut usize) -> Result<Vec<u8>, Err> { |
|
|
|
pub fn read_defl(b: &[u8], p: &mut usize) -> Result<Vec<u8>, Err> { |
|
|
|
let mut v = Vec::new(); |
|
|
|
|
|
|
|
loop { |
|
|
|
let bfinal = u8::read_bits_le(b, *p, 1).ok_or(Err::Block)?; |
|
|
|
let bstype = u8::read_bits_le(b, *p + 1, 2).ok_or(Err::Block)?; |
|
|
|
let bfinal = u8::read_bits_le(b, *p, 1).ok_or(Err::BlockBits)?; |
|
|
|
let bstype = u8::read_bits_le(b, *p + 1, 2).ok_or(Err::BlockBits)?; |
|
|
|
*p += 3; |
|
|
|
|
|
|
|
match bstype { |
|
|
|
0b10 => st_dynamic(b, p, &mut v)?, |
|
|
|
0b01 => st_s_table(b, p, &mut v)?, |
|
|
|
0b00 => st_literal(b, p, &mut v)?, |
|
|
|
_ => return Err(Err::BSTyp), |
|
|
|
_ => return Err(Err::BlockType), |
|
|
|
} |
|
|
|
|
|
|
|
if bfinal == 1 { |
|
|
@@ -133,9 +133,9 @@ fn st_dynamic(b: &[u8], p: &mut usize, v: &mut Vec<u8>) -> Result<(), Err> { |
|
|
|
// read the header: number of literal alphabet codes, number of |
|
|
|
// distance alphabet codes, and number of lengths for decoding the |
|
|
|
// alphabet |
|
|
|
let hlits = usize::read_bits_le(b, *p, 5).ok_or(Err::DyStr)?; |
|
|
|
let hdist = usize::read_bits_le(b, *p + 5, 5).ok_or(Err::DyStr)?; |
|
|
|
let hclen = usize::read_bits_le(b, *p + 10, 4).ok_or(Err::DyStr)?; |
|
|
|
let hlits = usize::read_bits_le(b, *p, 5).ok_or(Err::DynStream)?; |
|
|
|
let hdist = usize::read_bits_le(b, *p + 5, 5).ok_or(Err::DynStream)?; |
|
|
|
let hclen = usize::read_bits_le(b, *p + 10, 4).ok_or(Err::DynStream)?; |
|
|
|
*p += 14; |
|
|
|
|
|
|
|
let hlits = NHLITS + hlits; |
|
|
@@ -146,7 +146,7 @@ fn st_dynamic(b: &[u8], p: &mut usize, v: &mut Vec<u8>) -> Result<(), Err> { |
|
|
|
// compressed |
|
|
|
let mut table = [0; 19]; |
|
|
|
for &i in CODE_ORDERING.iter().take(hclen) { |
|
|
|
table[i] = u16::read_bits_le(b, *p, 3).ok_or(Err::DyStr)?; |
|
|
|
table[i] = u16::read_bits_le(b, *p, 3).ok_or(Err::DynStream)?; |
|
|
|
*p += 3; |
|
|
|
} |
|
|
|
|
|
|
@@ -156,7 +156,7 @@ fn st_dynamic(b: &[u8], p: &mut usize, v: &mut Vec<u8>) -> Result<(), Err> { |
|
|
|
let alpha = read_alphabet(b, p, hlits + hdist, &table)?; |
|
|
|
|
|
|
|
if alpha[256] == 0 { |
|
|
|
Err(Err::DyStr) |
|
|
|
Err(Err::DynStream) |
|
|
|
} else { |
|
|
|
// build the length and distance tables from this information |
|
|
|
let table_len = HuffmanTable::read(&alpha[0..hlits])?; |
|
|
@@ -189,12 +189,12 @@ fn st_literal(b: &[u8], p: &mut usize, v: &mut Vec<u8>) -> Result<(), Err> { |
|
|
|
// copy data directly from byte boundary |
|
|
|
let bound = *p / 8 + 1; |
|
|
|
let b = &b[bound..]; |
|
|
|
let len = read::u16le_sz(b.get(0..2).ok_or(Err::Liter)?, 0); |
|
|
|
let len = read::u16le_sz(b.get(0..2).ok_or(Err::Literal)?, 0); |
|
|
|
let b = &b[4..]; |
|
|
|
*p += bound * 8 + 4 * 8 + len * 8; |
|
|
|
|
|
|
|
if len > b.len() { |
|
|
|
Err(Err::Liter) |
|
|
|
Err(Err::Literal) |
|
|
|
} else { |
|
|
|
v.extend(&b[..len]); |
|
|
|
Ok(()) |
|
|
@@ -202,7 +202,7 @@ fn st_literal(b: &[u8], p: &mut usize, v: &mut Vec<u8>) -> Result<(), Err> { |
|
|
|
} |
|
|
|
|
|
|
|
fn next_alpha(alpha: &mut [u16], i: &mut usize, n: u16) -> Result<(), Err> { |
|
|
|
*alpha.get_mut(*i).ok_or(Err::CodeN)? = n; |
|
|
|
*alpha.get_mut(*i).ok_or(Err::AlphaIndex)? = n; |
|
|
|
*i += 1; |
|
|
|
Ok(()) |
|
|
|
} |
|
|
@@ -226,8 +226,8 @@ fn read_alphabet( |
|
|
|
} |
|
|
|
16 => { |
|
|
|
// copy previous code 3-6 times |
|
|
|
let lst = *alpha.get(i - 1).ok_or(Err::CodeC)?; |
|
|
|
let len = u8::read_bits_le(b, *p, 2).ok_or(Err::CodeC)? + 3; |
|
|
|
let lst = *alpha.get(i - 1).ok_or(Err::BitsCode)?; |
|
|
|
let len = u8::read_bits_le(b, *p, 2).ok_or(Err::BitsCode)? + 3; |
|
|
|
*p += 2; |
|
|
|
|
|
|
|
for _ in 0..len { |
|
|
@@ -236,7 +236,7 @@ fn read_alphabet( |
|
|
|
} |
|
|
|
17 => { |
|
|
|
// repeat '0' 3-10 times |
|
|
|
let len = u8::read_bits_le(b, *p, 3).ok_or(Err::Code0)? + 3; |
|
|
|
let len = u8::read_bits_le(b, *p, 3).ok_or(Err::Bits0)? + 3; |
|
|
|
*p += 3; |
|
|
|
|
|
|
|
for _ in 0..len { |
|
|
@@ -245,7 +245,7 @@ fn read_alphabet( |
|
|
|
} |
|
|
|
18 => { |
|
|
|
// repeat '0' 11-138 times |
|
|
|
let len = u8::read_bits_le(b, *p, 7).ok_or(Err::Code0)? + 11; |
|
|
|
let len = u8::read_bits_le(b, *p, 7).ok_or(Err::Bits0)? + 11; |
|
|
|
*p += 7; |
|
|
|
|
|
|
|
for _ in 0..len { |
|
|
@@ -253,7 +253,7 @@ fn read_alphabet( |
|
|
|
} |
|
|
|
} |
|
|
|
_ => { |
|
|
|
return Err(Err::Symbl); |
|
|
|
return Err(Err::Symbol); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
@@ -309,11 +309,11 @@ fn output_tables( |
|
|
|
let sym = usize::from(ty - 257); |
|
|
|
|
|
|
|
if sym > 29 { |
|
|
|
return Err(Err::Fixed); |
|
|
|
return Err(Err::Pair); |
|
|
|
} |
|
|
|
|
|
|
|
let bit = LEN_EXTRA_BITS[sym]; |
|
|
|
let len = usize::read_bits_le(b, *p, bit).ok_or(Err::Fixed)?; |
|
|
|
let len = usize::read_bits_le(b, *p, bit).ok_or(Err::Pair)?; |
|
|
|
|
|
|
|
*p += usize::from(bit); |
|
|
|
|
|
|
@@ -325,7 +325,7 @@ fn output_tables( |
|
|
|
let sym = usize::from(table_dst.decode(b, p)?); |
|
|
|
|
|
|
|
let bit = DST_EXTRA_BITS[sym]; |
|
|
|
let dst = usize::read_bits_le(b, *p, bit).ok_or(Err::Fixed)?; |
|
|
|
let dst = usize::read_bits_le(b, *p, bit).ok_or(Err::Pair)?; |
|
|
|
|
|
|
|
*p += usize::from(bit); |
|
|
|
|
|
|
@@ -333,7 +333,7 @@ fn output_tables( |
|
|
|
}; |
|
|
|
|
|
|
|
if dst > v.len() { |
|
|
|
return Err(Err::Distn); |
|
|
|
return Err(Err::Distance); |
|
|
|
} |
|
|
|
|
|
|
|
// copy bytes from earlier |
|
|
@@ -406,7 +406,7 @@ impl HuffmanTable { |
|
|
|
codes <<= 1; |
|
|
|
} |
|
|
|
|
|
|
|
Err(Err::Decod) |
|
|
|
Err(Err::TableDecode) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|