From d2ccfc16f71a06e5b048bfb55c18a217ca68b3d0 Mon Sep 17 00:00:00 2001 From: Mathijs van de Nes Date: Sun, 17 Jun 2018 15:16:14 +0200 Subject: [PATCH] Speed up Drop of ZipFileReader Skip CRC and decompression when dropping an owned ZipFileReader --- src/crc32.rs | 4 ++++ src/read.rs | 15 ++++++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/crc32.rs b/src/crc32.rs index 5e8a341e..35e6b2c5 100644 --- a/src/crc32.rs +++ b/src/crc32.rs @@ -87,6 +87,10 @@ impl Crc32Reader { self.check == self.crc } + + pub fn into_inner(self) -> R { + self.inner + } } impl Read for Crc32Reader diff --git a/src/read.rs b/src/read.rs index 1f4a4eb1..e6e982be 100644 --- a/src/read.rs +++ b/src/read.rs @@ -78,6 +78,7 @@ pub struct ZipArchive } enum ZipFileReader<'a> { + NoReader, Stored(Crc32Reader>), #[cfg(feature = "flate2")] Deflated(Crc32Reader>>), @@ -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 { match *reader { + ZipFileReader::NoReader => panic!("ZipFileReader was in an invalid state"), ZipFileReader::Stored(ref mut r) => r as &mut Read, #[cfg(feature = "flate2")] 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. if let Cow::Owned(_) = self.data { 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 { match reader.read(&mut buffer) { Ok(0) => break,