Speed up Drop of ZipFileReader

Skip CRC and decompression when dropping an owned ZipFileReader
This commit is contained in:
Mathijs van de Nes 2018-06-17 15:16:14 +02:00
parent 38d1699853
commit d2ccfc16f7
2 changed files with 18 additions and 1 deletions

View file

@ -87,6 +87,10 @@ impl<R> Crc32Reader<R>
{ {
self.check == self.crc self.check == self.crc
} }
pub fn into_inner(self) -> R {
self.inner
}
} }
impl<R: Read> Read for Crc32Reader<R> impl<R: Read> Read for Crc32Reader<R>

View file

@ -78,6 +78,7 @@ pub struct ZipArchive<R: Read + io::Seek>
} }
enum ZipFileReader<'a> { enum ZipFileReader<'a> {
NoReader,
Stored(Crc32Reader<io::Take<&'a mut Read>>), Stored(Crc32Reader<io::Take<&'a mut Read>>),
#[cfg(feature = "flate2")] #[cfg(feature = "flate2")]
Deflated(Crc32Reader<flate2::read::DeflateDecoder<io::Take<&'a mut Read>>>), Deflated(Crc32Reader<flate2::read::DeflateDecoder<io::Take<&'a mut Read>>>),
@ -415,6 +416,7 @@ fn parse_extra_field(file: &mut ZipFileData, data: &[u8]) -> ZipResult<()>
fn get_reader<'a>(reader: &'a mut ZipFileReader) -> &'a mut Read { fn get_reader<'a>(reader: &'a mut ZipFileReader) -> &'a mut Read {
match *reader { match *reader {
ZipFileReader::NoReader => panic!("ZipFileReader was in an invalid state"),
ZipFileReader::Stored(ref mut r) => r as &mut Read, ZipFileReader::Stored(ref mut r) => r as &mut Read,
#[cfg(feature = "flate2")] #[cfg(feature = "flate2")]
ZipFileReader::Deflated(ref mut r) => r as &mut Read, ZipFileReader::Deflated(ref mut r) => r as &mut Read,
@ -514,7 +516,18 @@ impl<'a> Drop for ZipFile<'a> {
// In this case, we want to exhaust the reader so that the next file is accessible. // In this case, we want to exhaust the reader so that the next file is accessible.
if let Cow::Owned(_) = self.data { if let Cow::Owned(_) = self.data {
let mut buffer = [0; 1<<16]; let mut buffer = [0; 1<<16];
let reader = get_reader(&mut self.reader);
// Get the inner `Take` reader so all decompression and CRC calculation is skipped.
let innerreader = ::std::mem::replace(&mut self.reader, ZipFileReader::NoReader);
let mut reader = match innerreader {
ZipFileReader::NoReader => panic!("ZipFileReader was in an invalid state"),
ZipFileReader::Stored(crcreader) => crcreader.into_inner(),
#[cfg(feature = "flate2")]
ZipFileReader::Deflated(crcreader) => crcreader.into_inner().into_inner(),
#[cfg(feature = "bzip2")]
ZipFileReader::Bzip2(crcreader) => crcreader.into_inner().into_inner(),
};
loop { loop {
match reader.read(&mut buffer) { match reader.read(&mut buffer) {
Ok(0) => break, Ok(0) => break,