Skip to content

Commit

Permalink
replace old read_gz_header
Browse files Browse the repository at this point in the history
  • Loading branch information
quininer committed Feb 15, 2019
1 parent 9dc0d9e commit c96b7b7
Showing 1 changed file with 30 additions and 86 deletions.
116 changes: 30 additions & 86 deletions src/gz/bufread.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,91 +30,17 @@ fn bad_header() -> io::Error {
io::Error::new(io::ErrorKind::InvalidInput, "invalid gzip header")
}

fn read_le_u16<R: Read>(r: &mut R) -> io::Result<u16> {
let mut b = [0; 2];
r.read_exact(&mut b)?;
Ok((b[0] as u16) | ((b[1] as u16) << 8))
}

pub(crate) fn read_gz_header<R: Read>(r: &mut R) -> io::Result<GzHeader> {
let mut crc_reader = CrcReader::new(r);
let mut header = [0; 10];
crc_reader.read_exact(&mut header)?;

let id1 = header[0];
let id2 = header[1];
if id1 != 0x1f || id2 != 0x8b {
return Err(bad_header());
}
let cm = header[2];
if cm != 8 {
return Err(bad_header());
}

let flg = header[3];
let mtime = ((header[4] as u32) << 0)
| ((header[5] as u32) << 8)
| ((header[6] as u32) << 16)
| ((header[7] as u32) << 24);
let _xfl = header[8];
let os = header[9];

let extra = if flg & FEXTRA != 0 {
let xlen = read_le_u16(&mut crc_reader)?;
let mut extra = vec![0; xlen as usize];
crc_reader.read_exact(&mut extra)?;
Some(extra)
} else {
None
};
let filename = if flg & FNAME != 0 {
// wow this is slow
let mut b = Vec::new();
for byte in crc_reader.by_ref().bytes() {
let byte = byte?;
if byte == 0 {
break;
}
b.push(byte);
}
Some(b)
} else {
None
};
let comment = if flg & FCOMMENT != 0 {
// wow this is slow
let mut b = Vec::new();
for byte in crc_reader.by_ref().bytes() {
let byte = byte?;
if byte == 0 {
break;
}
b.push(byte);
}
Some(b)
} else {
None
};

if flg & FHCRC != 0 {
let calced_crc = crc_reader.crc().sum() as u16;
let stored_crc = read_le_u16(&mut crc_reader)?;
if calced_crc != stored_crc {
return Err(corrupt());
}
}

Ok(GzHeader {
extra: extra,
filename: filename,
comment: comment,
operating_system: os,
mtime: mtime,
})
let mut state = GzHeaderState::Header(0, [0; 10]);
let mut header = GzHeader::default();
let mut flag = 0;
let mut hasher = Hasher::new();
read_gz_header2(r, &mut state, &mut header, &mut flag, &mut hasher)
.map(|_| header)
}

#[derive(Debug)]
pub(crate) enum GzHeaderState {
enum GzHeaderState {
Header(usize, [u8; 10]), // pos, buf
ExtraLen(usize, [u8; 2]), // pos, buf
Extra(usize), // pos
Expand All @@ -123,7 +49,7 @@ pub(crate) enum GzHeaderState {
Crc(u16, usize, [u8; 2]) // crc, pos, buf
}

pub(crate) fn read_gz_header2<R: BufRead>(
fn read_gz_header2<R: Read>(
r: &mut R,
state: &mut GzHeaderState,
header: &mut GzHeader,
Expand Down Expand Up @@ -214,17 +140,35 @@ pub(crate) fn read_gz_header2<R: BufRead>(
GzHeaderState::FileName if *flag & FNAME == 0 => next = Next::Comment,
GzHeaderState::FileName => {
let filename = header.filename.get_or_insert_with(Vec::new);
r.read_until(0, filename)?;

// wow this is slow
for byte in r.by_ref().bytes() {
let byte = byte?;
if byte == 0 {
break;
}
filename.push(byte);
}

hasher.update(filename);
filename.pop(); // pop 0
hasher.update(&[0]);
next = Next::Comment;
},
GzHeaderState::Comment if *flag & FCOMMENT == 0 => next = Next::Crc,
GzHeaderState::Comment => {
let comment = header.comment.get_or_insert_with(Vec::new);
r.read_until(0, comment)?;

// wow this is slow
for byte in r.by_ref().bytes() {
let byte = byte?;
if byte == 0 {
break;
}
comment.push(byte);
}

hasher.update(comment);
comment.pop(); // pop 0
hasher.update(&[0]);
next = Next::Crc
},
GzHeaderState::Crc(..) if *flag & FHCRC == 0 => return Ok(()),
Expand Down

0 comments on commit c96b7b7

Please sign in to comment.