diff --git a/.github/workflows/cifuzz.yml b/.github/workflows/cifuzz.yml new file mode 100644 index 00000000..ea8cae60 --- /dev/null +++ b/.github/workflows/cifuzz.yml @@ -0,0 +1,26 @@ +name: CIFuzz +on: [pull_request] +jobs: + Fuzzing: + runs-on: ubuntu-latest + steps: + - name: Build Fuzzers + id: build + uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master + with: + oss-fuzz-project-name: 'flate2-rs' + dry-run: false + language: rust + - name: Run Fuzzers + uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@master + with: + oss-fuzz-project-name: 'flate2-rs' + fuzz-seconds: 180 + dry-run: false + language: rust + - name: Upload Crash + uses: actions/upload-artifact@v3 + if: failure() && steps.build.outcome == 'success' + with: + name: artifacts + path: ./out/artifacts diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 9f04add4..ba72877f 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -38,12 +38,19 @@ jobs: - run: cargo test - run: cargo test --features zlib - run: cargo test --features zlib --no-default-features + - run: cargo test --features zlib-default --no-default-features - run: cargo test --features zlib-ng-compat --no-default-features if: matrix.build != 'mingw' - run: cargo test --features zlib-ng --no-default-features if: matrix.build != 'mingw' - run: cargo test --features cloudflare_zlib --no-default-features if: matrix.build != 'mingw' + - run: | + if ! cargo check --no-default-features 2>&1 | grep "You need to choose"; then + echo "expected message stating a zlib backend must be chosen" + exit 1 + fi + if: matrix.build == 'stable' rustfmt: name: Rustfmt diff --git a/Cargo.toml b/Cargo.toml index 10cf92ec..0dbe5397 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,13 +32,14 @@ quickcheck = { version = "1.0", default-features = false } [features] default = ["rust_backend"] -any_zlib = [] # note: this is not a real user-facing feature +any_zlib = ["any_impl"] # note: this is not a real user-facing feature +any_impl = [] # note: this is not a real user-facing feature zlib = ["any_zlib", "libz-sys"] zlib-default = ["any_zlib", "libz-sys/default"] zlib-ng-compat = ["zlib", "libz-sys/zlib-ng"] zlib-ng = ["any_zlib", "libz-ng-sys"] cloudflare_zlib = ["any_zlib", "cloudflare-zlib-sys"] -rust_backend = ["miniz_oxide"] +rust_backend = ["miniz_oxide", "any_impl"] miniz-sys = ["rust_backend"] # For backwards compatibility [package.metadata.docs.rs] diff --git a/src/deflate/read.rs b/src/deflate/read.rs index e6af130a..5937e6f6 100644 --- a/src/deflate/read.rs +++ b/src/deflate/read.rs @@ -25,11 +25,11 @@ use crate::bufreader::BufReader; /// # /// // Return a vector containing the Deflate compressed version of hello world /// fn deflateencoder_read_hello_world() -> io::Result> { -/// let mut ret_vec = [0;100]; +/// let mut ret_vec = Vec::new(); /// let c = b"hello world"; /// let mut deflater = DeflateEncoder::new(&c[..], Compression::fast()); -/// let count = deflater.read(&mut ret_vec)?; -/// Ok(ret_vec[0..count].to_vec()) +/// deflater.read_to_end(&mut ret_vec)?; +/// Ok(ret_vec) /// } /// ``` #[derive(Debug)] diff --git a/src/ffi/mod.rs b/src/ffi/mod.rs index 8bac6e42..20b3cae6 100644 --- a/src/ffi/mod.rs +++ b/src/ffi/mod.rs @@ -40,9 +40,9 @@ mod c; #[cfg(feature = "any_zlib")] pub use self::c::*; -#[cfg(not(feature = "any_zlib"))] +#[cfg(all(not(feature = "any_zlib"), feature = "miniz_oxide"))] mod rust; -#[cfg(not(feature = "any_zlib"))] +#[cfg(all(not(feature = "any_zlib"), feature = "miniz_oxide"))] pub use self::rust::*; impl std::fmt::Debug for ErrorMessage { diff --git a/src/gz/bufread.rs b/src/gz/bufread.rs index b59bf21c..c008b372 100644 --- a/src/gz/bufread.rs +++ b/src/gz/bufread.rs @@ -167,6 +167,7 @@ impl Write for GzEncoder { /// /// This structure consumes a [`BufRead`] interface, reading compressed data /// from the underlying reader, and emitting uncompressed data. +/// Use [`MultiGzDecoder`] if your file has multiple streams. /// /// [`BufRead`]: https://doc.rust-lang.org/std/io/trait.BufRead.html /// @@ -344,9 +345,11 @@ impl Write for GzDecoder { /// A gzip member consists of a header, compressed data and a trailer. The [gzip /// specification](https://tools.ietf.org/html/rfc1952), however, allows multiple /// gzip members to be joined in a single stream. `MultiGzDecoder` will -/// decode all consecutive members while `GzDecoder` will only decompress +/// decode all consecutive members while [`GzDecoder`] will only decompress /// the first gzip member. The multistream format is commonly used in -/// bioinformatics, for example when using the BGZF compressed data. +/// bioinformatics, for example when using the BGZF compressed data. It's also useful +/// to compress large amounts of data in parallel where each thread produces one stream +/// for a chunk of input data. /// /// This structure exposes a [`BufRead`] interface that will consume all gzip members /// from the underlying reader and emit uncompressed data. diff --git a/src/gz/read.rs b/src/gz/read.rs index 2b0796b2..196598c5 100644 --- a/src/gz/read.rs +++ b/src/gz/read.rs @@ -25,11 +25,11 @@ use crate::Compression; /// // Return a vector containing the GZ compressed version of hello world /// /// fn gzencode_hello_world() -> io::Result> { -/// let mut ret_vec = [0;100]; +/// let mut ret_vec = Vec::new(); /// let bytestring = b"hello world"; /// let mut gz = GzEncoder::new(&bytestring[..], Compression::fast()); -/// let count = gz.read(&mut ret_vec)?; -/// Ok(ret_vec[0..count].to_vec()) +/// gz.read_to_end(&mut ret_vec)?; +/// Ok(ret_vec) /// } /// ``` #[derive(Debug)] @@ -94,13 +94,13 @@ impl Write for GzEncoder { /// /// This structure exposes a [`Read`] interface that will consume compressed /// data from the underlying reader and emit uncompressed data. +/// Use [`MultiGzDecoder`] if your file has multiple streams. /// /// [`Read`]: https://doc.rust-lang.org/std/io/trait.Read.html /// /// # Examples /// /// ``` -/// /// use std::io::prelude::*; /// use std::io; /// # use flate2::Compression; @@ -185,9 +185,11 @@ impl Write for GzDecoder { /// A gzip member consists of a header, compressed data and a trailer. The [gzip /// specification](https://tools.ietf.org/html/rfc1952), however, allows multiple /// gzip members to be joined in a single stream. `MultiGzDecoder` will -/// decode all consecutive members while `GzDecoder` will only decompress the +/// decode all consecutive members while [`GzDecoder`] will only decompress the /// first gzip member. The multistream format is commonly used in bioinformatics, -/// for example when using the BGZF compressed data. +/// for example when using the BGZF compressed data. It's also useful +/// to compress large amounts of data in parallel where each thread produces one stream +/// for a chunk of input data. /// /// This structure exposes a [`Read`] interface that will consume all gzip members /// from the underlying reader and emit uncompressed data. diff --git a/src/gz/write.rs b/src/gz/write.rs index 339914d0..de128123 100644 --- a/src/gz/write.rs +++ b/src/gz/write.rs @@ -170,6 +170,7 @@ impl Drop for GzEncoder { /// /// This structure exposes a [`Write`] interface that will emit uncompressed data /// to the underlying writer `W`. +/// Use [`MultiGzDecoder`] if your file has multiple streams. /// /// [`Write`]: https://doc.rust-lang.org/std/io/trait.Write.html /// diff --git a/src/lib.rs b/src/lib.rs index 6789c5b7..738875c5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -78,6 +78,9 @@ #![cfg_attr(test, deny(warnings))] #![cfg_attr(docsrs, feature(doc_auto_cfg))] +#[cfg(not(feature = "any_impl",))] +compile_error!("You need to choose a zlib backend"); + pub use crate::crc::{Crc, CrcReader, CrcWriter}; pub use crate::gz::GzBuilder; pub use crate::gz::GzHeader; @@ -154,7 +157,7 @@ fn _assert_send_sync() { } /// When compressing data, the compression level can be specified by a value in -/// this enum. +/// this struct. #[derive(Copy, Clone, PartialEq, Eq, Debug)] pub struct Compression(u32); diff --git a/src/zlib/read.rs b/src/zlib/read.rs index 33021304..94ca805a 100644 --- a/src/zlib/read.rs +++ b/src/zlib/read.rs @@ -24,9 +24,9 @@ use crate::bufreader::BufReader; /// # fn open_hello_world() -> std::io::Result> { /// let f = File::open("examples/hello_world.txt")?; /// let mut z = ZlibEncoder::new(f, Compression::fast()); -/// let mut buffer = [0;50]; -/// let byte_count = z.read(&mut buffer)?; -/// # Ok(buffer[0..byte_count].to_vec()) +/// let mut buffer = Vec::new(); +/// z.read_to_end(&mut buffer)?; +/// # Ok(buffer) /// # } /// ``` #[derive(Debug)]