From fee626ba5971bab8509ee6f6c08ffee47f02c499 Mon Sep 17 00:00:00 2001
From: Alexander Bulaev <alexbool@yandex-team.ru>
Date: Sat, 19 May 2018 20:03:23 +0300
Subject: [PATCH] Control backend choice of flate2

---
 .travis.yml        |  2 ++
 Cargo.toml         |  6 ++++--
 README.md          | 12 ++++++++++++
 appveyor.yml       |  1 +
 src/compression.rs | 14 +++++++-------
 src/lib.rs         |  2 +-
 src/read.rs        | 10 +++++-----
 src/write.rs       | 18 +++++++++---------
 8 files changed, 41 insertions(+), 24 deletions(-)

diff --git a/.travis.yml b/.travis.yml
index 85769bd1..21f65247 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -14,6 +14,8 @@ notifications:
 script:
     - cargo test
     - cargo test --no-default-features
+    - cargo test --no-default-features --features "deflate-zlib"
+    - cargo test --no-default-features --features "deflate-miniz"
     - cargo doc --no-deps
     - rustdoc --test README.md -L target/debug
 
diff --git a/Cargo.toml b/Cargo.toml
index b5b8c556..b51826e7 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -12,7 +12,7 @@ Library to support the reading and writing of zip files.
 """
 
 [dependencies]
-flate2 = { version = "1.0", default-features = false, features = ["rust_backend"], optional = true}
+flate2 = { version = "1.0", default-features = false, optional = true }
 time = "0.1"
 podio = "0.1"
 msdos_time = "0.1"
@@ -22,5 +22,7 @@ bzip2 = { version = "0.3", optional = true }
 walkdir = "1.0"
 
 [features]
-deflate = ["flate2"]
+deflate = ["flate2", "flate2/rust_backend"]
+deflate-miniz = ["flate2", "flate2/miniz-sys"]
+deflate-zlib = ["flate2", "flate2/zlib"]
 default = ["bzip2", "deflate"]
diff --git a/README.md b/README.md
index ba38d842..f7b9d3ae 100644
--- a/README.md
+++ b/README.md
@@ -43,6 +43,18 @@ Without the default features:
 zip = { version = "0.3", default-features = false }
 ```
 
+You can further control the backend of `deflate` compression method with these features:
+* `deflate` (enabled by default) uses [miniz_oxide](https://github.com/Frommi/miniz_oxide)
+* `deflate-miniz` uses [miniz](https://github.com/richgel999/miniz)
+* `deflate-zlib` uses zlib
+
+For example:
+
+```toml
+[dependencies]
+zip = { version = "0.3", features = ["deflate-zlib"], default-features = false }
+```
+
 Examples
 --------
 
diff --git a/appveyor.yml b/appveyor.yml
index 67321b4b..b9450e3c 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -42,3 +42,4 @@ build: false
 test_script:
   - cargo test
   - cargo test --no-default-features
+  - cargo test --no-default-features --features "deflate-miniz"
diff --git a/src/compression.rs b/src/compression.rs
index 774c68c3..79c41a8f 100644
--- a/src/compression.rs
+++ b/src/compression.rs
@@ -9,7 +9,7 @@ pub enum CompressionMethod
     /// The file is stored (no compression)
     Stored,
     /// The file is Deflated
-    #[cfg(feature = "deflate")]
+    #[cfg(feature = "flate2")]
     Deflated,
     /// File is compressed using BZIP2 algorithm
     #[cfg(feature = "bzip2")]
@@ -23,7 +23,7 @@ impl CompressionMethod {
     pub fn from_u16(val: u16) -> CompressionMethod {
         match val {
             0 => CompressionMethod::Stored,
-            #[cfg(feature = "deflate")]
+            #[cfg(feature = "flate2")]
             8 => CompressionMethod::Deflated,
             #[cfg(feature = "bzip2")]
             12 => CompressionMethod::Bzip2,
@@ -35,7 +35,7 @@ impl CompressionMethod {
     pub fn to_u16(self) -> u16 {
         match self {
             CompressionMethod::Stored => 0,
-            #[cfg(feature = "deflate")]
+            #[cfg(feature = "flate2")]
             CompressionMethod::Deflated => 8,
             #[cfg(feature = "bzip2")]
             CompressionMethod::Bzip2 => 12,
@@ -65,22 +65,22 @@ mod test {
         }
     }
 
-    #[cfg(all(not(feature = "bzip2"), feature = "deflate"))]
+    #[cfg(all(not(feature = "bzip2"), feature = "flate2"))]
     fn methods() -> Vec<CompressionMethod> {
         vec![CompressionMethod::Stored, CompressionMethod::Deflated]
     }
 
-    #[cfg(all(not(feature = "deflate"), feature = "bzip2"))]
+    #[cfg(all(not(feature = "flate2"), feature = "bzip2"))]
     fn methods() -> Vec<CompressionMethod> {
         vec![CompressionMethod::Stored, CompressionMethod::Bzip2]
     }
 
-    #[cfg(all(feature = "bzip2", feature = "deflate"))]
+    #[cfg(all(feature = "bzip2", feature = "flate2"))]
     fn methods() -> Vec<CompressionMethod> {
         vec![CompressionMethod::Stored, CompressionMethod::Deflated, CompressionMethod::Bzip2]
     }
 
-    #[cfg(all(not(feature = "bzip2"), not(feature = "deflate")))]
+    #[cfg(all(not(feature = "bzip2"), not(feature = "flate2")))]
     fn methods() -> Vec<CompressionMethod> {
         vec![CompressionMethod::Stored]
     }
diff --git a/src/lib.rs b/src/lib.rs
index de78fcf3..f694dfc0 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -4,7 +4,7 @@
 
 #[cfg(feature = "bzip2")]
 extern crate bzip2;
-#[cfg(feature = "deflate")]
+#[cfg(feature = "flate2")]
 extern crate flate2;
 extern crate msdos_time;
 extern crate podio;
diff --git a/src/read.rs b/src/read.rs
index 9dfc7f38..a0e36a59 100644
--- a/src/read.rs
+++ b/src/read.rs
@@ -13,9 +13,9 @@ use types::{ZipFileData, System};
 use cp437::FromCp437;
 use msdos_time::{TmMsDosExt, MsDosDateTime};
 
-#[cfg(feature = "deflate")]
+#[cfg(feature = "flate2")]
 use flate2;
-#[cfg(feature = "deflate")]
+#[cfg(feature = "flate2")]
 use flate2::read::DeflateDecoder;
 
 #[cfg(feature = "bzip2")]
@@ -77,7 +77,7 @@ pub struct ZipArchive<R: Read + io::Seek>
 
 enum ZipFileReader<'a> {
     Stored(Crc32Reader<io::Take<&'a mut Read>>),
-    #[cfg(feature = "deflate")]
+    #[cfg(feature = "flate2")]
     Deflated(Crc32Reader<flate2::read::DeflateDecoder<io::Take<&'a mut Read>>>),
     #[cfg(feature = "bzip2")]
     Bzip2(Crc32Reader<BzDecoder<io::Take<&'a mut Read>>>),
@@ -254,7 +254,7 @@ impl<R: Read+io::Seek> ZipArchive<R>
                     limit_reader,
                     data.crc32))
             },
-            #[cfg(feature = "deflate")]
+            #[cfg(feature = "flate2")]
             CompressionMethod::Deflated =>
             {
                 let deflate_reader = DeflateDecoder::new(limit_reader);
@@ -397,7 +397,7 @@ impl<'a> ZipFile<'a> {
     fn get_reader(&mut self) -> &mut Read {
         match self.reader {
            ZipFileReader::Stored(ref mut r) => r as &mut Read,
-           #[cfg(feature = "deflate")]
+           #[cfg(feature = "flate2")]
            ZipFileReader::Deflated(ref mut r) => r as &mut Read,
            #[cfg(feature = "bzip2")]
            ZipFileReader::Bzip2(ref mut r) => r as &mut Read,
diff --git a/src/write.rs b/src/write.rs
index 74d1df18..03283f70 100644
--- a/src/write.rs
+++ b/src/write.rs
@@ -13,9 +13,9 @@ use time;
 use podio::{WritePodExt, LittleEndian};
 use msdos_time::TmMsDosExt;
 
-#[cfg(feature = "deflate")]
+#[cfg(feature = "flate2")]
 use flate2;
-#[cfg(feature = "deflate")]
+#[cfg(feature = "flate2")]
 use flate2::write::DeflateEncoder;
 
 #[cfg(feature = "bzip2")]
@@ -29,7 +29,7 @@ enum GenericZipWriter<W: Write + io::Seek>
 {
     Closed,
     Storer(W),
-    #[cfg(feature = "deflate")]
+    #[cfg(feature = "flate2")]
     Deflater(DeflateEncoder<W>),
     #[cfg(feature = "bzip2")]
     Bzip2(BzEncoder<W>),
@@ -83,7 +83,7 @@ pub struct FileOptions {
 }
 
 impl FileOptions {
-    #[cfg(feature = "deflate")]
+    #[cfg(feature = "flate2")]
     /// Construct a new FileOptions object
     pub fn default() -> FileOptions {
         FileOptions {
@@ -93,7 +93,7 @@ impl FileOptions {
         }
     }
 
-    #[cfg(not(feature = "deflate"))]
+    #[cfg(not(feature = "flate2"))]
     /// Construct a new FileOptions object
     pub fn default() -> FileOptions {
         FileOptions {
@@ -349,7 +349,7 @@ impl<W: Write+io::Seek> GenericZipWriter<W>
         let bare = match mem::replace(self, GenericZipWriter::Closed)
         {
             GenericZipWriter::Storer(w) => w,
-            #[cfg(feature = "deflate")]
+            #[cfg(feature = "flate2")]
             GenericZipWriter::Deflater(w) => try!(w.finish()),
             #[cfg(feature = "bzip2")]
             GenericZipWriter::Bzip2(w) => try!(w.finish()),
@@ -359,7 +359,7 @@ impl<W: Write+io::Seek> GenericZipWriter<W>
         *self = match compression
         {
             CompressionMethod::Stored => GenericZipWriter::Storer(bare),
-            #[cfg(feature = "deflate")]
+            #[cfg(feature = "flate2")]
             CompressionMethod::Deflated => GenericZipWriter::Deflater(DeflateEncoder::new(bare, flate2::Compression::default())),
             #[cfg(feature = "bzip2")]
             CompressionMethod::Bzip2 => GenericZipWriter::Bzip2(BzEncoder::new(bare, bzip2::Compression::Default)),
@@ -372,7 +372,7 @@ impl<W: Write+io::Seek> GenericZipWriter<W>
     fn ref_mut(&mut self) -> Option<&mut Write> {
         match *self {
             GenericZipWriter::Storer(ref mut w) => Some(w as &mut Write),
-            #[cfg(feature = "deflate")]
+            #[cfg(feature = "flate2")]
             GenericZipWriter::Deflater(ref mut w) => Some(w as &mut Write),
             #[cfg(feature = "bzip2")]
             GenericZipWriter::Bzip2(ref mut w) => Some(w as &mut Write),
@@ -401,7 +401,7 @@ impl<W: Write+io::Seek> GenericZipWriter<W>
     fn current_compression(&self) -> Option<CompressionMethod> {
         match *self {
             GenericZipWriter::Storer(..) => Some(CompressionMethod::Stored),
-            #[cfg(feature = "deflate")]
+            #[cfg(feature = "flate2")]
             GenericZipWriter::Deflater(..) => Some(CompressionMethod::Deflated),
             #[cfg(feature = "bzip2")]
             GenericZipWriter::Bzip2(..) => Some(CompressionMethod::Bzip2),