88 lines
1.5 KiB
Rust
88 lines
1.5 KiB
Rust
//! DEFLATE loader.
|
|
|
|
use crate::durandal::err::*;
|
|
|
|
/// Loads a ZLIB file header.
|
|
pub fn load_zlib_header(b: &[u8]) -> ResultS<usize>
|
|
{
|
|
const CM: u8 = 0b00001111;
|
|
const CINFO: u8 = 0b11110000;
|
|
const FDICT: u8 = 0b00100000;
|
|
|
|
read_data! {
|
|
2, BE in b =>
|
|
fcheck = u16[0];
|
|
cmf = u8[0];
|
|
flg = u8[1];
|
|
}
|
|
|
|
let cm = cmf & CM;
|
|
let cinfo = cmf & CINFO >> 4;
|
|
|
|
if cm != 8 || fcheck % 31 != 0 || cinfo > 7 {
|
|
bail!("not zlib format");
|
|
}
|
|
|
|
if flg & FDICT != 0 {
|
|
bail!("dictionary not supported");
|
|
}
|
|
|
|
Ok(2)
|
|
}
|
|
|
|
/// Loads a GZIP file header.
|
|
pub fn load_gzip_header(b: &[u8]) -> ResultS<usize>
|
|
{
|
|
const FHCRC: u8 = 1 << 1;
|
|
const FEXTRA: u8 = 1 << 2;
|
|
const FNAME: u8 = 1 << 3;
|
|
const FCOMMENT: u8 = 1 << 4;
|
|
|
|
read_data! {
|
|
10, LE in b =>
|
|
id = u16[0];
|
|
cm = u8[2];
|
|
fl = u8[3];
|
|
}
|
|
|
|
if id != 0x8B1F || cm != 8 {
|
|
bail!("not gzip format");
|
|
}
|
|
|
|
let mut p = 10;
|
|
|
|
if fl & FEXTRA != 0 {
|
|
read_data!(p + 2, LE in b => xlen = u16[p] usize;);
|
|
check_data!(p + 2 + xlen, b);
|
|
|
|
p += xlen;
|
|
}
|
|
|
|
if fl & FNAME != 0 {
|
|
p = skip_zero_terminated_item(&b[p..])?;
|
|
}
|
|
|
|
if fl & FCOMMENT != 0 {
|
|
p = skip_zero_terminated_item(&b[p..])?;
|
|
}
|
|
|
|
if fl & FHCRC != 0 {
|
|
check_data!(p + 2, b);
|
|
|
|
p += 2;
|
|
}
|
|
|
|
Ok(p)
|
|
}
|
|
|
|
fn skip_zero_terminated_item(b: &[u8]) -> ResultS<usize>
|
|
{
|
|
if let Some(i) = b.iter().position(|&n| n == 0) {
|
|
Ok(i)
|
|
} else {
|
|
bail!("no end of zero terminated item");
|
|
}
|
|
}
|
|
|
|
// EOF
|