Enable deflated compression method for any flate2 backend

Allow using other than default flate2 backend for deflated compression 
method. The motivation for this change was to allow using different 
backends in dependent crates.
This commit is contained in:
Piotr Maks 2020-05-28 22:53:25 +02:00
parent b36340e779
commit d1bdd552e9
4 changed files with 96 additions and 20 deletions

View file

@ -14,9 +14,17 @@ fn main() {
const METHOD_STORED: Option<zip::CompressionMethod> = Some(zip::CompressionMethod::Stored);
#[cfg(feature = "deflate")]
#[cfg(any(
feature = "deflate",
feature = "deflate-miniz",
feature = "deflate-zlib"
))]
const METHOD_DEFLATED: Option<zip::CompressionMethod> = Some(zip::CompressionMethod::Deflated);
#[cfg(not(feature = "deflate"))]
#[cfg(not(any(
feature = "deflate",
feature = "deflate-miniz",
feature = "deflate-zlib"
)))]
const METHOD_DEFLATED: Option<zip::CompressionMethod> = None;
#[cfg(feature = "bzip2")]

View file

@ -7,8 +7,12 @@ use std::fmt;
pub enum CompressionMethod {
/// The file is stored (no compression)
Stored,
/// Deflate in pure rust
#[cfg(feature = "deflate")]
/// Deflate using any flate2 backend
#[cfg(any(
feature = "deflate",
feature = "deflate-miniz",
feature = "deflate-zlib"
))]
Deflated,
/// File is compressed using BZIP2 algorithm
#[cfg(feature = "bzip2")]
@ -22,7 +26,11 @@ impl CompressionMethod {
pub fn from_u16(val: u16) -> CompressionMethod {
match val {
0 => CompressionMethod::Stored,
#[cfg(feature = "deflate")]
#[cfg(any(
feature = "deflate",
feature = "deflate-miniz",
feature = "deflate-zlib"
))]
8 => CompressionMethod::Deflated,
#[cfg(feature = "bzip2")]
12 => CompressionMethod::Bzip2,
@ -34,7 +42,11 @@ impl CompressionMethod {
pub fn to_u16(self) -> u16 {
match self {
CompressionMethod::Stored => 0,
#[cfg(feature = "deflate")]
#[cfg(any(
feature = "deflate",
feature = "deflate-miniz",
feature = "deflate-zlib"
))]
CompressionMethod::Deflated => 8,
#[cfg(feature = "bzip2")]
CompressionMethod::Bzip2 => 12,
@ -66,7 +78,11 @@ mod test {
fn methods() -> Vec<CompressionMethod> {
let mut methods = Vec::new();
methods.push(CompressionMethod::Stored);
#[cfg(feature = "deflate")]
#[cfg(any(
feature = "deflate",
feature = "deflate-miniz",
feature = "deflate-zlib"
))]
methods.push(CompressionMethod::Deflated);
#[cfg(feature = "bzip2")]
methods.push(CompressionMethod::Bzip2);

View file

@ -13,7 +13,11 @@ use crate::cp437::FromCp437;
use crate::types::{DateTime, System, ZipFileData};
use podio::{LittleEndian, ReadPodExt};
#[cfg(feature = "deflate")]
#[cfg(any(
feature = "deflate",
feature = "deflate-miniz",
feature = "deflate-zlib"
))]
use flate2::read::DeflateDecoder;
#[cfg(feature = "bzip2")]
@ -279,7 +283,11 @@ impl<R: Read + io::Seek> ZipArchive<R> {
enum ZipFileReader<'a> {
NoReader,
Stored(Crc32Reader<io::Take<&'a mut dyn Read>>),
#[cfg(feature = "deflate")]
#[cfg(any(
feature = "deflate",
feature = "deflate-miniz",
feature = "deflate-zlib"
))]
Deflated(Crc32Reader<flate2::read::DeflateDecoder<io::Take<&'a mut dyn Read>>>),
#[cfg(feature = "bzip2")]
Bzip2(Crc32Reader<BzDecoder<io::Take<&'a mut dyn Read>>>),
@ -296,7 +304,11 @@ fn make_reader<'a>(
) -> ZipResult<ZipFileReader<'a>> {
match compression_method {
CompressionMethod::Stored => Ok(ZipFileReader::Stored(Crc32Reader::new(reader, crc32))),
#[cfg(feature = "deflate")]
#[cfg(any(
feature = "deflate",
feature = "deflate-miniz",
feature = "deflate-zlib"
))]
CompressionMethod::Deflated => {
let deflate_reader = DeflateDecoder::new(reader);
Ok(ZipFileReader::Deflated(Crc32Reader::new(
@ -420,7 +432,11 @@ fn get_reader<'a>(reader: &'a mut ZipFileReader<'_>) -> &'a mut dyn Read {
match *reader {
ZipFileReader::NoReader => panic!("ZipFileReader was in an invalid state"),
ZipFileReader::Stored(ref mut r) => r as &mut dyn Read,
#[cfg(feature = "deflate")]
#[cfg(any(
feature = "deflate",
feature = "deflate-miniz",
feature = "deflate-zlib"
))]
ZipFileReader::Deflated(ref mut r) => r as &mut dyn Read,
#[cfg(feature = "bzip2")]
ZipFileReader::Bzip2(ref mut r) => r as &mut dyn Read,
@ -560,7 +576,11 @@ impl<'a> Drop for ZipFile<'a> {
let mut reader = match innerreader {
ZipFileReader::NoReader => panic!("ZipFileReader was in an invalid state"),
ZipFileReader::Stored(crcreader) => crcreader.into_inner(),
#[cfg(feature = "deflate")]
#[cfg(any(
feature = "deflate",
feature = "deflate-miniz",
feature = "deflate-zlib"
))]
ZipFileReader::Deflated(crcreader) => crcreader.into_inner().into_inner(),
#[cfg(feature = "bzip2")]
ZipFileReader::Bzip2(crcreader) => crcreader.into_inner().into_inner(),

View file

@ -11,7 +11,11 @@ use std::io;
use std::io::prelude::*;
use std::mem;
#[cfg(feature = "deflate")]
#[cfg(any(
feature = "deflate",
feature = "deflate-miniz",
feature = "deflate-zlib"
))]
use flate2::write::DeflateEncoder;
#[cfg(feature = "bzip2")]
@ -20,7 +24,11 @@ use bzip2::write::BzEncoder;
enum GenericZipWriter<W: Write + io::Seek> {
Closed,
Storer(W),
#[cfg(feature = "deflate")]
#[cfg(any(
feature = "deflate",
feature = "deflate-miniz",
feature = "deflate-zlib"
))]
Deflater(DeflateEncoder<W>),
#[cfg(feature = "bzip2")]
Bzip2(BzEncoder<W>),
@ -77,9 +85,17 @@ impl FileOptions {
/// Construct a new FileOptions object
pub fn default() -> FileOptions {
FileOptions {
#[cfg(feature = "deflate")]
#[cfg(any(
feature = "deflate",
feature = "deflate-miniz",
feature = "deflate-zlib"
))]
compression_method: CompressionMethod::Deflated,
#[cfg(not(feature = "deflate"))]
#[cfg(not(any(
feature = "deflate",
feature = "deflate-miniz",
feature = "deflate-zlib"
)))]
compression_method: CompressionMethod::Stored,
#[cfg(feature = "time")]
last_modified_time: DateTime::from_time(time::now()).unwrap_or_default(),
@ -384,7 +400,11 @@ impl<W: Write + io::Seek> GenericZipWriter<W> {
let bare = match mem::replace(self, GenericZipWriter::Closed) {
GenericZipWriter::Storer(w) => w,
#[cfg(feature = "deflate")]
#[cfg(any(
feature = "deflate",
feature = "deflate-miniz",
feature = "deflate-zlib"
))]
GenericZipWriter::Deflater(w) => w.finish()?,
#[cfg(feature = "bzip2")]
GenericZipWriter::Bzip2(w) => w.finish()?,
@ -399,7 +419,11 @@ impl<W: Write + io::Seek> GenericZipWriter<W> {
*self = match compression {
CompressionMethod::Stored => GenericZipWriter::Storer(bare),
#[cfg(feature = "deflate")]
#[cfg(any(
feature = "deflate",
feature = "deflate-miniz",
feature = "deflate-zlib"
))]
CompressionMethod::Deflated => GenericZipWriter::Deflater(DeflateEncoder::new(
bare,
flate2::Compression::default(),
@ -419,7 +443,11 @@ impl<W: Write + io::Seek> GenericZipWriter<W> {
fn ref_mut(&mut self) -> Option<&mut dyn Write> {
match *self {
GenericZipWriter::Storer(ref mut w) => Some(w as &mut dyn Write),
#[cfg(feature = "deflate")]
#[cfg(any(
feature = "deflate",
feature = "deflate-miniz",
feature = "deflate-zlib"
))]
GenericZipWriter::Deflater(ref mut w) => Some(w as &mut dyn Write),
#[cfg(feature = "bzip2")]
GenericZipWriter::Bzip2(ref mut w) => Some(w as &mut dyn Write),
@ -444,7 +472,11 @@ impl<W: Write + io::Seek> GenericZipWriter<W> {
fn current_compression(&self) -> Option<CompressionMethod> {
match *self {
GenericZipWriter::Storer(..) => Some(CompressionMethod::Stored),
#[cfg(feature = "deflate")]
#[cfg(any(
feature = "deflate",
feature = "deflate-miniz",
feature = "deflate-zlib"
))]
GenericZipWriter::Deflater(..) => Some(CompressionMethod::Deflated),
#[cfg(feature = "bzip2")]
GenericZipWriter::Bzip2(..) => Some(CompressionMethod::Bzip2),