Add zlib-ng

This commit is contained in:
Chris Hennick 2023-05-30 09:18:26 -07:00
parent d9c20c55c4
commit 9ec0ddc5ca
No known key found for this signature in database
GPG key ID: 25653935CC8B6C74
7 changed files with 100 additions and 99 deletions

View file

@ -190,4 +190,10 @@
### Added ### Added
- Zopfli for aggressive Deflate compression. - Zopfli for aggressive Deflate compression.
## [0.9.2]
### Added
- `zlib-ng` for fast Deflate compression. This is now the default for compression levels 0-9.

View file

@ -1,6 +1,6 @@
[package] [package]
name = "zip_next" name = "zip_next"
version = "0.9.1" version = "0.9.2"
authors = ["Mathijs van de Nes <git@mathijs.vd-nes.nl>", "Marli Frost <marli@frost.red>", "Ryan Levick <ryan.levick@gmail.com>", authors = ["Mathijs van de Nes <git@mathijs.vd-nes.nl>", "Marli Frost <marli@frost.red>", "Ryan Levick <ryan.levick@gmail.com>",
"Chris Hennick <hennickc@amazon.com>"] "Chris Hennick <hennickc@amazon.com>"]
license = "MIT" license = "MIT"
@ -43,9 +43,10 @@ aes-crypto = [ "aes", "constant_time_eq", "hmac", "pbkdf2", "sha1" ]
deflate = ["flate2/rust_backend"] deflate = ["flate2/rust_backend"]
deflate-miniz = ["flate2/default"] deflate-miniz = ["flate2/default"]
deflate-zlib = ["flate2/zlib"] deflate-zlib = ["flate2/zlib"]
deflate-zlib-ng = ["flate2/zlib-ng"]
deflate-zopfli = ["zopfli"] deflate-zopfli = ["zopfli"]
unreserved = [] unreserved = []
default = ["aes-crypto", "bzip2", "deflate", "deflate-zopfli", "time", "zstd"] default = ["aes-crypto", "bzip2", "deflate", "deflate-zlib-ng", "deflate-zopfli", "time", "zstd"]
[[bench]] [[bench]]
name = "read_entry" name = "read_entry"

View file

@ -4,7 +4,7 @@ zip_next
[![Build Status](https://github.com/Pr0methean/zip-next/actions/workflows/ci.yaml/badge.svg)](https://github.com/Pr0methean/zip-next/actions?query=branch%3Amaster+workflow%3ACI) [![Build Status](https://github.com/Pr0methean/zip-next/actions/workflows/ci.yaml/badge.svg)](https://github.com/Pr0methean/zip-next/actions?query=branch%3Amaster+workflow%3ACI)
[![Crates.io version](https://img.shields.io/crates/v/zip_next.svg)](https://crates.io/crates/zip_next) [![Crates.io version](https://img.shields.io/crates/v/zip_next.svg)](https://crates.io/crates/zip_next)
[Documentation](https://docs.rs/zip_next/0.9.1/zip_next/) [Documentation](https://docs.rs/zip_next/0.9.2/zip_next/)
Info Info
---- ----
@ -32,25 +32,31 @@ With all default features:
```toml ```toml
[dependencies] [dependencies]
zip_next = "0.9.1" zip_next = "0.9.2"
``` ```
Without the default features: Without the default features:
```toml ```toml
[dependencies] [dependencies]
zip_next = { version = "0.9.1", default-features = false } zip_next = { version = "0.9.2", default-features = false }
``` ```
The features available are: The features available are:
* `aes-crypto`: Enables decryption of files which were encrypted with AES. Supports AE-1 and AE-2 methods. * `aes-crypto`: Enables decryption of files which were encrypted with AES. Supports AE-1 and AE-2 methods.
* `deflate`: Enables the deflate compression algorithm, which is the default for zip files. * `deflate`: Enables decompressing the deflate compression algorithm, which is the default for zip files.
* `deflate-miniz`: Enables deflating files with the `miniz_oxide` library (used when compression quality is 0..=9).
* `deflate-zlib`: Enables deflating files with the `zlib` library (used when compression quality is 0..=9).
* `deflate-zlib-ng`: Enables deflating files with the `zlib-ng` library (used when compression quality is 0..=9).
This is the fastest `deflate` implementation available.
* `deflate-zopfli`: Enables deflating files with the `zopfli` library (used when compression quality is 10..=264). This
is the most effective `deflate` implementation available.
* `bzip2`: Enables the BZip2 compression algorithm. * `bzip2`: Enables the BZip2 compression algorithm.
* `time`: Enables features using the [time](https://github.com/rust-lang-deprecated/time) crate. * `time`: Enables features using the [time](https://github.com/rust-lang-deprecated/time) crate.
* `zstd`: Enables the Zstandard compression algorithm. * `zstd`: Enables the Zstandard compression algorithm.
All of these are enabled by default. By default `aes-crypto`, `deflate`, `deflate-zlib-ng`, `deflate-zopfli`, `bzip2`, `time` and `zstd` are enabled.
MSRV MSRV
---- ----

View file

@ -18,14 +18,17 @@ const METHOD_STORED: Option<zip_next::CompressionMethod> =
#[cfg(any( #[cfg(any(
feature = "deflate", feature = "deflate",
feature = "deflate-miniz", feature = "deflate-miniz",
feature = "deflate-zlib" feature = "deflate-zlib",
feature = "deflate-zlib-ng"
))] ))]
const METHOD_DEFLATED: Option<zip_next::CompressionMethod> = const METHOD_DEFLATED: Option<zip_next::CompressionMethod> =
Some(zip_next::CompressionMethod::Deflated); Some(zip_next::CompressionMethod::Deflated);
#[cfg(not(any( #[cfg(not(any(
feature = "deflate", feature = "deflate",
feature = "deflate-miniz", feature = "deflate-miniz",
feature = "deflate-zlib" feature = "deflate-zlib",
feature = "deflate-zlib-ng",
feature = "deflate-zopfli"
)))] )))]
const METHOD_DEFLATED: Option<zip_next::CompressionMethod> = None; const METHOD_DEFLATED: Option<zip_next::CompressionMethod> = None;

View file

@ -21,6 +21,7 @@ pub enum CompressionMethod {
feature = "deflate", feature = "deflate",
feature = "deflate-miniz", feature = "deflate-miniz",
feature = "deflate-zlib", feature = "deflate-zlib",
feature = "deflate-zlib-ng",
feature = "deflate-zopfli" feature = "deflate-zopfli"
))] ))]
Deflated, Deflated,
@ -57,6 +58,7 @@ impl CompressionMethod {
feature = "deflate", feature = "deflate",
feature = "deflate-miniz", feature = "deflate-miniz",
feature = "deflate-zlib", feature = "deflate-zlib",
feature = "deflate-zlib-ng",
feature = "deflate-zopfli" feature = "deflate-zopfli"
))] ))]
pub const DEFLATE: Self = CompressionMethod::Deflated; pub const DEFLATE: Self = CompressionMethod::Deflated;
@ -64,6 +66,7 @@ impl CompressionMethod {
feature = "deflate", feature = "deflate",
feature = "deflate-miniz", feature = "deflate-miniz",
feature = "deflate-zlib", feature = "deflate-zlib",
feature = "deflate-zlib-ng",
feature = "deflate-zopfli" feature = "deflate-zopfli"
)))] )))]
pub const DEFLATE: Self = CompressionMethod::Unsupported(8); pub const DEFLATE: Self = CompressionMethod::Unsupported(8);
@ -105,6 +108,7 @@ impl CompressionMethod {
feature = "deflate", feature = "deflate",
feature = "deflate-miniz", feature = "deflate-miniz",
feature = "deflate-zlib", feature = "deflate-zlib",
feature = "deflate-zlib-ng",
feature = "deflate-zopfli" feature = "deflate-zopfli"
))] ))]
8 => CompressionMethod::Deflated, 8 => CompressionMethod::Deflated,
@ -132,6 +136,7 @@ impl CompressionMethod {
feature = "deflate", feature = "deflate",
feature = "deflate-miniz", feature = "deflate-miniz",
feature = "deflate-zlib", feature = "deflate-zlib",
feature = "deflate-zlib-ng",
feature = "deflate-zopfli" feature = "deflate-zopfli"
))] ))]
CompressionMethod::Deflated => 8, CompressionMethod::Deflated => 8,
@ -161,6 +166,7 @@ pub const SUPPORTED_COMPRESSION_METHODS: &[CompressionMethod] = &[
feature = "deflate", feature = "deflate",
feature = "deflate-miniz", feature = "deflate-miniz",
feature = "deflate-zlib", feature = "deflate-zlib",
feature = "deflate-zlib-ng",
feature = "deflate-zopfli" feature = "deflate-zopfli"
))] ))]
CompressionMethod::Deflated, CompressionMethod::Deflated,

View file

@ -19,7 +19,8 @@ use std::sync::Arc;
#[cfg(any( #[cfg(any(
feature = "deflate", feature = "deflate",
feature = "deflate-miniz", feature = "deflate-miniz",
feature = "deflate-zlib" feature = "deflate-zlib",
feature = "deflate-zlib-ng"
))] ))]
use flate2::read::DeflateDecoder; use flate2::read::DeflateDecoder;
@ -126,7 +127,8 @@ pub(crate) enum ZipFileReader<'a> {
#[cfg(any( #[cfg(any(
feature = "deflate", feature = "deflate",
feature = "deflate-miniz", feature = "deflate-miniz",
feature = "deflate-zlib" feature = "deflate-zlib",
feature = "deflate-zlib-ng"
))] ))]
Deflated(Crc32Reader<DeflateDecoder<CryptoReader<'a>>>), Deflated(Crc32Reader<DeflateDecoder<CryptoReader<'a>>>),
#[cfg(feature = "bzip2")] #[cfg(feature = "bzip2")]
@ -144,7 +146,8 @@ impl<'a> Read for ZipFileReader<'a> {
#[cfg(any( #[cfg(any(
feature = "deflate", feature = "deflate",
feature = "deflate-miniz", feature = "deflate-miniz",
feature = "deflate-zlib" feature = "deflate-zlib",
feature = "deflate-zlib-ng"
))] ))]
ZipFileReader::Deflated(r) => r.read(buf), ZipFileReader::Deflated(r) => r.read(buf),
#[cfg(feature = "bzip2")] #[cfg(feature = "bzip2")]
@ -165,7 +168,8 @@ impl<'a> ZipFileReader<'a> {
#[cfg(any( #[cfg(any(
feature = "deflate", feature = "deflate",
feature = "deflate-miniz", feature = "deflate-miniz",
feature = "deflate-zlib" feature = "deflate-zlib",
feature = "deflate-zlib-ng"
))] ))]
ZipFileReader::Deflated(r) => r.into_inner().into_inner().into_inner(), ZipFileReader::Deflated(r) => r.into_inner().into_inner().into_inner(),
#[cfg(feature = "bzip2")] #[cfg(feature = "bzip2")]
@ -271,7 +275,8 @@ pub(crate) fn make_reader(
#[cfg(any( #[cfg(any(
feature = "deflate", feature = "deflate",
feature = "deflate-miniz", feature = "deflate-miniz",
feature = "deflate-zlib" feature = "deflate-zlib",
feature = "deflate-zlib-ng"
))] ))]
CompressionMethod::Deflated => { CompressionMethod::Deflated => {
let deflate_reader = DeflateDecoder::new(reader); let deflate_reader = DeflateDecoder::new(reader);

View file

@ -21,7 +21,8 @@ use std::sync::Arc;
#[cfg(any( #[cfg(any(
feature = "deflate", feature = "deflate",
feature = "deflate-miniz", feature = "deflate-miniz",
feature = "deflate-zlib" feature = "deflate-zlib",
feature = "deflate-zlib-ng"
))] ))]
use flate2::write::DeflateEncoder; use flate2::write::DeflateEncoder;
@ -60,7 +61,8 @@ enum GenericZipWriter<W: Write + Seek> {
#[cfg(any( #[cfg(any(
feature = "deflate", feature = "deflate",
feature = "deflate-miniz", feature = "deflate-miniz",
feature = "deflate-zlib" feature = "deflate-zlib",
feature = "deflate-zlib-ng"
))] ))]
Deflater(DeflateEncoder<MaybeEncrypted<W>>), Deflater(DeflateEncoder<MaybeEncrypted<W>>),
#[cfg(feature = "deflate-zopfli")] #[cfg(feature = "deflate-zopfli")]
@ -348,13 +350,16 @@ impl Default for FileOptions {
#[cfg(any( #[cfg(any(
feature = "deflate", feature = "deflate",
feature = "deflate-miniz", feature = "deflate-miniz",
feature = "deflate-zlib" feature = "deflate-zlib",
feature = "deflate-zlib-ng",
feature = "deflate-zopfli"
))] ))]
compression_method: Deflated, compression_method: Deflated,
#[cfg(not(any( #[cfg(not(any(
feature = "deflate", feature = "deflate",
feature = "deflate-miniz", feature = "deflate-miniz",
feature = "deflate-zlib", feature = "deflate-zlib",
feature = "deflate-zlib-ng",
feature = "deflate-zopfli" feature = "deflate-zopfli"
)))] )))]
compression_method: Stored, compression_method: Stored,
@ -1157,6 +1162,7 @@ impl<W: Write + Seek> GenericZipWriter<W> {
{ {
#[allow(deprecated)] #[allow(deprecated)]
#[allow(unreachable_code)]
match compression { match compression {
Stored => { Stored => {
if compression_level.is_some() { if compression_level.is_some() {
@ -1171,23 +1177,19 @@ impl<W: Write + Seek> GenericZipWriter<W> {
feature = "deflate", feature = "deflate",
feature = "deflate-miniz", feature = "deflate-miniz",
feature = "deflate-zlib", feature = "deflate-zlib",
feature = "deflate-zlib-ng",
feature = "deflate-zopfli" feature = "deflate-zopfli"
))] ))]
Deflated => { Deflated => {
#[cfg(all( let default = if cfg!(feature = "deflate")
not(feature = "deflate"), || cfg!(feature = "deflate-miniz")
not(feature = "deflate-miniz"), || cfg!(feature = "deflate-zlib")
not(feature = "deflate-zlib"), || cfg!(feature = "deflate-zlib-ng")
feature = "deflate-zopfli" {
))] Compression::default().level() as i32
let default = 24; } else {
24
#[cfg(any( };
feature = "deflate",
feature = "deflate-miniz",
feature = "deflate-zlib"
))]
let default = Compression::default().level() as i32;
let level = clamp_opt( let level = clamp_opt(
compression_level.unwrap_or(default), compression_level.unwrap_or(default),
@ -1197,48 +1199,8 @@ impl<W: Write + Seek> GenericZipWriter<W> {
"Unsupported compression level", "Unsupported compression level",
))? as u32; ))? as u32;
#[cfg(not(feature = "deflate-zopfli"))] #[cfg(feature = "deflate-zopfli")]
return Ok(Box::new(move |bare| { {
GenericZipWriter::Deflater(DeflateEncoder::new(
bare,
flate2::Compression::new(level),
))
}));
#[cfg(all(
not(feature = "deflate"),
not(feature = "deflate-miniz"),
not(feature = "deflate-zlib"),
feature = "deflate-zopfli"
))]
return Ok(Box::new(move |bare| {
let mut options = Options::default();
options.iteration_count =
NonZeroU8::try_from((level - best_non_zopfli) as u8).unwrap();
match deflate_buffer_size {
Some(size) => {
GenericZipWriter::BufferedZopfliDeflater(BufWriter::with_capacity(
size,
zopfli::DeflateEncoder::new(options, Default::default(), bare),
))
}
None => GenericZipWriter::ZopfliDeflater(zopfli::DeflateEncoder::new(
options,
Default::default(),
bare,
)),
}
}));
#[cfg(all(
any(
feature = "deflate",
feature = "deflate-miniz",
feature = "deflate-zlib"
),
feature = "deflate-zopfli"
))]
Ok(Box::new(move |bare| {
let best_non_zopfli = Compression::best().level(); let best_non_zopfli = Compression::best().level();
if level > best_non_zopfli { if level > best_non_zopfli {
let options = Options { let options = Options {
@ -1248,7 +1210,7 @@ impl<W: Write + Seek> GenericZipWriter<W> {
.unwrap(), .unwrap(),
..Default::default() ..Default::default()
}; };
match zopfli_buffer_size { return Ok(Box::new(move |bare| match zopfli_buffer_size {
Some(size) => GenericZipWriter::BufferedZopfliDeflater( Some(size) => GenericZipWriter::BufferedZopfliDeflater(
BufWriter::with_capacity( BufWriter::with_capacity(
size, size,
@ -1262,14 +1224,25 @@ impl<W: Write + Seek> GenericZipWriter<W> {
None => GenericZipWriter::ZopfliDeflater( None => GenericZipWriter::ZopfliDeflater(
zopfli::DeflateEncoder::new(options, Default::default(), bare), zopfli::DeflateEncoder::new(options, Default::default(), bare),
), ),
} }));
} else { }
}
#[cfg(any(
feature = "deflate",
feature = "deflate-miniz",
feature = "deflate-zlib",
feature = "deflate-zlib-ng",
))]
{
return Ok(Box::new(move |bare| {
GenericZipWriter::Deflater(DeflateEncoder::new( GenericZipWriter::Deflater(DeflateEncoder::new(
bare, bare,
Compression::new(level), Compression::new(level),
)) ))
} }));
})) }
unreachable!()
} }
#[cfg(feature = "bzip2")] #[cfg(feature = "bzip2")]
CompressionMethod::Bzip2 => { CompressionMethod::Bzip2 => {
@ -1316,7 +1289,8 @@ impl<W: Write + Seek> GenericZipWriter<W> {
#[cfg(any( #[cfg(any(
feature = "deflate", feature = "deflate",
feature = "deflate-miniz", feature = "deflate-miniz",
feature = "deflate-zlib" feature = "deflate-zlib",
feature = "deflate-zlib-ng"
))] ))]
GenericZipWriter::Deflater(w) => w.finish()?, GenericZipWriter::Deflater(w) => w.finish()?,
#[cfg(feature = "deflate-zopfli")] #[cfg(feature = "deflate-zopfli")]
@ -1345,7 +1319,8 @@ impl<W: Write + Seek> GenericZipWriter<W> {
#[cfg(any( #[cfg(any(
feature = "deflate", feature = "deflate",
feature = "deflate-miniz", feature = "deflate-miniz",
feature = "deflate-zlib" feature = "deflate-zlib",
feature = "deflate-zlib-ng"
))] ))]
GenericZipWriter::Deflater(ref mut w) => Some(w as &mut dyn Write), GenericZipWriter::Deflater(ref mut w) => Some(w as &mut dyn Write),
#[cfg(feature = "deflate-zopfli")] #[cfg(feature = "deflate-zopfli")]
@ -1383,28 +1358,26 @@ impl<W: Write + Seek> GenericZipWriter<W> {
feature = "deflate", feature = "deflate",
feature = "deflate-miniz", feature = "deflate-miniz",
feature = "deflate-zlib", feature = "deflate-zlib",
feature = "deflate-zlib-ng",
feature = "deflate-zopfli" feature = "deflate-zopfli"
))] ))]
fn deflate_compression_level_range() -> std::ops::RangeInclusive<i32> { fn deflate_compression_level_range() -> std::ops::RangeInclusive<i32> {
#[cfg(any( let min = if cfg!(feature = "deflate")
feature = "deflate", || cfg!(feature = "deflate-miniz")
feature = "deflate-miniz", || cfg!(feature = "deflate-zlib")
feature = "deflate-zlib", || cfg!(feature = "deflate-zlib-ng")
))] {
let min = Compression::none().level() as i32; Compression::none().level() as i32
} else {
Compression::best().level() as i32 + 1
};
#[cfg(not(any( let max = Compression::best().level() as i32
feature = "deflate", + if cfg!(feature = "deflate-zopfli") {
feature = "deflate-miniz", u8::MAX as i32
feature = "deflate-zlib", } else {
)))] 0
let min = flate2::Compression::best().level() + 1 as i32; };
#[cfg(not(feature = "deflate-zopfli"))]
let max = flate2::Compression::best().level() as i32;
#[cfg(feature = "deflate-zopfli")]
let max = Compression::best().level() as i32 + u8::MAX as i32;
min..=max min..=max
} }
@ -1420,6 +1393,7 @@ fn bzip2_compression_level_range() -> std::ops::RangeInclusive<i32> {
feature = "deflate", feature = "deflate",
feature = "deflate-miniz", feature = "deflate-miniz",
feature = "deflate-zlib", feature = "deflate-zlib",
feature = "deflate-zlib-ng",
feature = "deflate-zopfli", feature = "deflate-zopfli",
feature = "bzip2", feature = "bzip2",
feature = "zstd" feature = "zstd"