flate2-1.0.22/.cargo_vcs_info.json0000644000000001120000000000100122650ustar { "git": { "sha1": "63ecb8c0407c619c7a20529699b89369061ece88" } } flate2-1.0.22/.gitattributes000064400000000000000000000004530072674642500140100ustar 00000000000000# automatically handle text files * text=auto # text files *.md text *.txt text # source code files *.rs text *.c text # configuration files *.yml text *.toml text # compressed files *.gz binary # no end-of-line normalization should take place for integration test text files tests/*.txt -text flate2-1.0.22/.github/workflows/main.yml000064400000000000000000000057660072674642500161750ustar 00000000000000name: CI on: [push, pull_request] jobs: test: name: Test runs-on: ${{ matrix.os }} strategy: matrix: # I don't really understand the build matrix here... build: [stable, beta, nightly, macos, windows, mingw] include: - build: stable os: ubuntu-latest rust: stable - build: beta os: ubuntu-latest rust: beta - build: nightly os: ubuntu-latest rust: nightly - build: macos os: macos-latest rust: stable - build: windows os: windows-latest rust: stable - build: mingw os: windows-latest rust: stable-x86_64-gnu steps: - uses: actions/checkout@master - name: Install Rust (rustup) run: rustup update ${{ matrix.rust }} --no-self-update && rustup default ${{ matrix.rust }} shell: bash - run: cargo build - run: rustdoc --test README.md -L target/debug/deps --extern flate2=target/debug/libflate2.rlib --edition=2018 - run: cargo test - run: cargo test --features zlib - run: cargo test --features miniz-sys - run: cargo test --features zlib --no-default-features - run: cargo test --features zlib-ng-compat --no-default-features - run: cargo test --features cloudflare_zlib --no-default-features if: matrix.build != 'mingw' - run: cargo test --features miniz-sys --no-default-features - run: cargo test --features tokio rustfmt: name: Rustfmt runs-on: ubuntu-latest steps: - uses: actions/checkout@master - name: Install Rust run: rustup update stable && rustup default stable && rustup component add rustfmt - run: cargo fmt -- --check systest: name: Systest runs-on: ubuntu-latest steps: - uses: actions/checkout@master - name: Install Rust run: rustup update stable && rustup default stable - run: cargo run --manifest-path systest/Cargo.toml wasm: name: WebAssembly runs-on: ubuntu-latest strategy: matrix: target: [wasm32-unknown-unknown, wasm32-wasi] steps: - uses: actions/checkout@master - name: Install Rust run: rustup update stable && rustup default stable && rustup target add ${{ matrix.target }} - run: cargo build --target ${{ matrix.target }} publish_docs: name: Publish Documentation runs-on: ubuntu-latest steps: - uses: actions/checkout@master - name: Install Rust run: rustup update stable && rustup default stable - name: Build documentation run: cargo doc --no-deps --all-features - name: Publish documentation run: | cd target/doc git init git add . git -c user.name='ci' -c user.email='ci' commit -m init git push -f -q https://git:${{ secrets.github_token }}@github.com/${{ github.repository }} HEAD:gh-pages if: github.event_name == 'push' && github.event.ref == 'refs/heads/master' flate2-1.0.22/.gitignore000064400000000000000000000000220072674642500130750ustar 00000000000000target Cargo.lock flate2-1.0.22/Cargo.lock0000644000000370730000000000100102600ustar # This file is automatically @generated by Cargo. # It is not intended for manual editing. version = 3 [[package]] name = "adler" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ee2a4ec343196209d6594e19543ae87a39f96d5534d7174822a3ad825dd6ed7e" [[package]] name = "autocfg" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" [[package]] name = "bitflags" version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" [[package]] name = "byteorder" version = "1.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de" [[package]] name = "bytes" version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" dependencies = [ "byteorder", "iovec", ] [[package]] name = "cc" version = "1.0.67" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3c69b077ad434294d3ce9f1f6143a2a4b89a8a2d54ef813d85003a4fd1137fd" [[package]] name = "cfg-if" version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" [[package]] name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "cloudabi" version = "0.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" dependencies = [ "bitflags", ] [[package]] name = "cloudflare-zlib-sys" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2040b6d1edfee6d75f172d81e2d2a7807534f3f294ce18184c70e7bb0105cd6f" dependencies = [ "cc", ] [[package]] name = "cmake" version = "0.1.45" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eb6210b637171dfba4cda12e579ac6dc73f5165ad56133e5d72ef3131f320855" dependencies = [ "cc", ] [[package]] name = "crc32fast" version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a" dependencies = [ "cfg-if 1.0.0", ] [[package]] name = "crossbeam-deque" version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f02af974daeee82218205558e51ec8768b48cf524bd01d550abe5573a608285" dependencies = [ "crossbeam-epoch", "crossbeam-utils", "maybe-uninit", ] [[package]] name = "crossbeam-epoch" version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "058ed274caafc1f60c4997b5fc07bf7dc7cca454af7c6e81edffe5f33f70dace" dependencies = [ "autocfg", "cfg-if 0.1.10", "crossbeam-utils", "lazy_static", "maybe-uninit", "memoffset", "scopeguard", ] [[package]] name = "crossbeam-queue" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "774ba60a54c213d409d5353bda12d49cd68d14e45036a285234c8d6f91f92570" dependencies = [ "cfg-if 0.1.10", "crossbeam-utils", "maybe-uninit", ] [[package]] name = "crossbeam-utils" version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8" dependencies = [ "autocfg", "cfg-if 0.1.10", "lazy_static", ] [[package]] name = "flate2" version = "1.0.22" dependencies = [ "cfg-if 1.0.0", "cloudflare-zlib-sys", "crc32fast", "futures", "libc", "libz-sys", "miniz-sys", "miniz_oxide", "quickcheck", "rand", "tokio-io", "tokio-tcp", "tokio-threadpool", ] [[package]] name = "fnv" version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "fuchsia-zircon" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" dependencies = [ "bitflags", "fuchsia-zircon-sys", ] [[package]] name = "fuchsia-zircon-sys" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" [[package]] name = "futures" version = "0.1.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c7e4c2612746b0df8fed4ce0c69156021b704c9aefa360311c04e6e9e002eed" [[package]] name = "getrandom" version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc587bc0ec293155d5bfa6b9891ec18a1e330c234f896ea47fbada4cadbe47e6" dependencies = [ "cfg-if 0.1.10", "libc", "wasi", ] [[package]] name = "hermit-abi" version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5aca5565f760fb5b220e499d72710ed156fdb74e631659e99377d9ebfbd13ae8" dependencies = [ "libc", ] [[package]] name = "iovec" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" dependencies = [ "libc", ] [[package]] name = "kernel32-sys" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" dependencies = [ "winapi 0.2.8", "winapi-build", ] [[package]] name = "lazy_static" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" version = "0.2.81" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1482821306169ec4d07f6aca392a4681f66c75c9918aa49641a2595db64053cb" [[package]] name = "libz-sys" version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "602113192b08db8f38796c4e85c39e960c145965140e918018bcde1952429655" dependencies = [ "cc", "cmake", "libc", "pkg-config", "vcpkg", ] [[package]] name = "lock_api" version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4da24a77a3d8a6d4862d95f72e6fdb9c09a643ecdb402d754004a557f2bec75" dependencies = [ "scopeguard", ] [[package]] name = "log" version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4fabed175da42fed1fa0746b0ea71f412aa9d35e76e95e59b192c64b9dc2bf8b" dependencies = [ "cfg-if 0.1.10", ] [[package]] name = "maybe-uninit" version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" [[package]] name = "memoffset" version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "043175f069eda7b85febe4a74abbaeff828d9f8b448515d3151a14a3542811aa" dependencies = [ "autocfg", ] [[package]] name = "miniz-sys" version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e9e3ae51cea1576ceba0dde3d484d30e6e5b86dee0b2d412fe3a16a15c98202" dependencies = [ "cc", "libc", ] [[package]] name = "miniz_oxide" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0f2d26ec3309788e423cfbf68ad1800f061638098d76a83681af979dc4eda19d" dependencies = [ "adler", "autocfg", ] [[package]] name = "mio" version = "0.6.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4afd66f5b91bf2a3bc13fad0e21caedac168ca4c707504e75585648ae80e4cc4" dependencies = [ "cfg-if 0.1.10", "fuchsia-zircon", "fuchsia-zircon-sys", "iovec", "kernel32-sys", "libc", "log", "miow", "net2", "slab", "winapi 0.2.8", ] [[package]] name = "miow" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ebd808424166322d4a38da87083bfddd3ac4c131334ed55856112eb06d46944d" dependencies = [ "kernel32-sys", "net2", "winapi 0.2.8", "ws2_32-sys", ] [[package]] name = "net2" version = "0.2.37" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "391630d12b68002ae1e25e8f974306474966550ad82dac6886fb8910c19568ae" dependencies = [ "cfg-if 0.1.10", "libc", "winapi 0.3.9", ] [[package]] name = "num_cpus" version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3" dependencies = [ "hermit-abi", "libc", ] [[package]] name = "parking_lot" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252" dependencies = [ "lock_api", "parking_lot_core", "rustc_version", ] [[package]] name = "parking_lot_core" version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b" dependencies = [ "cfg-if 0.1.10", "cloudabi", "libc", "redox_syscall", "rustc_version", "smallvec", "winapi 0.3.9", ] [[package]] name = "pkg-config" version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c" [[package]] name = "ppv-lite86" version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" [[package]] name = "quickcheck" version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a44883e74aa97ad63db83c4bf8ca490f02b2fc02f92575e720c8551e843c945f" dependencies = [ "rand", "rand_core", ] [[package]] name = "rand" version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" dependencies = [ "getrandom", "libc", "rand_chacha", "rand_core", "rand_hc", ] [[package]] name = "rand_chacha" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" dependencies = [ "ppv-lite86", "rand_core", ] [[package]] name = "rand_core" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" dependencies = [ "getrandom", ] [[package]] name = "rand_hc" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" dependencies = [ "rand_core", ] [[package]] name = "redox_syscall" version = "0.1.57" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce" [[package]] name = "rustc_version" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" dependencies = [ "semver", ] [[package]] name = "scopeguard" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] name = "semver" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" dependencies = [ "semver-parser", ] [[package]] name = "semver-parser" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[package]] name = "slab" version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" [[package]] name = "smallvec" version = "0.6.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f7b0758c52e15a8b5e3691eae6cc559f08eee9406e548a4477ba4e67770a82b6" dependencies = [ "maybe-uninit", ] [[package]] name = "tokio-executor" version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fb2d1b8f4548dbf5e1f7818512e9c406860678f29c300cdf0ebac72d1a3a1671" dependencies = [ "crossbeam-utils", "futures", ] [[package]] name = "tokio-io" version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57fc868aae093479e3131e3d165c93b1c7474109d13c90ec0dda2a1bbfff0674" dependencies = [ "bytes", "futures", "log", ] [[package]] name = "tokio-reactor" version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09bc590ec4ba8ba87652da2068d150dcada2cfa2e07faae270a5e0409aa51351" dependencies = [ "crossbeam-utils", "futures", "lazy_static", "log", "mio", "num_cpus", "parking_lot", "slab", "tokio-executor", "tokio-io", "tokio-sync", ] [[package]] name = "tokio-sync" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "edfe50152bc8164fcc456dab7891fa9bf8beaf01c5ee7e1dd43a397c3cf87dee" dependencies = [ "fnv", "futures", ] [[package]] name = "tokio-tcp" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "98df18ed66e3b72e742f185882a9e201892407957e45fbff8da17ae7a7c51f72" dependencies = [ "bytes", "futures", "iovec", "mio", "tokio-io", "tokio-reactor", ] [[package]] name = "tokio-threadpool" version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df720b6581784c118f0eb4310796b12b1d242a7eb95f716a8367855325c25f89" dependencies = [ "crossbeam-deque", "crossbeam-queue", "crossbeam-utils", "futures", "lazy_static", "log", "num_cpus", "slab", "tokio-executor", ] [[package]] name = "vcpkg" version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b00bca6106a5e23f3eee943593759b7fcddb00554332e856d990c893966879fb" [[package]] name = "wasi" version = "0.9.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" [[package]] name = "winapi" version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" [[package]] name = "winapi" version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" dependencies = [ "winapi-i686-pc-windows-gnu", "winapi-x86_64-pc-windows-gnu", ] [[package]] name = "winapi-build" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" [[package]] name = "winapi-i686-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "ws2_32-sys" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" dependencies = [ "winapi 0.2.8", "winapi-build", ] flate2-1.0.22/Cargo.toml0000644000000045150000000000100102760ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2018" name = "flate2" version = "1.0.22" authors = ["Alex Crichton ", "Josh Triplett "] description = "DEFLATE compression and decompression exposed as Read/BufRead/Write streams.\nSupports miniz_oxide, miniz.c, and multiple zlib implementations. Supports\nzlib, gzip, and raw deflate streams.\n" homepage = "https://github.com/rust-lang/flate2-rs" documentation = "https://docs.rs/flate2" readme = "README.md" keywords = ["gzip", "deflate", "zlib", "zlib-ng", "encoding"] categories = ["compression", "api-bindings"] license = "MIT/Apache-2.0" repository = "https://github.com/rust-lang/flate2-rs" [dependencies.cfg-if] version = "1.0.0" [dependencies.cloudflare-zlib-sys] version = "0.3.0" optional = true [dependencies.crc32fast] version = "1.2.0" [dependencies.futures] version = "0.1.25" optional = true [dependencies.libc] version = "0.2.65" [dependencies.libz-sys] version = "1.1.0" optional = true default-features = false [dependencies.miniz-sys] version = "0.1.11" optional = true [dependencies.miniz_oxide] version = "0.4.0" optional = true default-features = false [dependencies.tokio-io] version = "0.1.11" optional = true [dev-dependencies.futures] version = "0.1" [dev-dependencies.quickcheck] version = "0.9" default-features = false [dev-dependencies.rand] version = "0.7" [dev-dependencies.tokio-io] version = "0.1.11" [dev-dependencies.tokio-tcp] version = "0.1.3" [dev-dependencies.tokio-threadpool] version = "0.1.10" [features] any_zlib = [] cloudflare_zlib = ["any_zlib", "cloudflare-zlib-sys"] default = ["rust_backend"] rust_backend = ["miniz_oxide"] tokio = ["tokio-io", "futures"] zlib = ["any_zlib", "libz-sys"] zlib-ng-compat = ["zlib", "libz-sys/zlib-ng"] [target."cfg(all(target_arch = \"wasm32\", not(target_os = \"emscripten\")))".dependencies.miniz_oxide] version = "0.4.0" default-features = false flate2-1.0.22/Cargo.toml.orig000064400000000000000000000033670072674642500140130ustar 00000000000000[package] name = "flate2" authors = ["Alex Crichton ", "Josh Triplett "] version = "1.0.22" edition = "2018" license = "MIT/Apache-2.0" readme = "README.md" keywords = ["gzip", "deflate", "zlib", "zlib-ng", "encoding"] categories = ["compression", "api-bindings"] repository = "https://github.com/rust-lang/flate2-rs" homepage = "https://github.com/rust-lang/flate2-rs" documentation = "https://docs.rs/flate2" description = """ DEFLATE compression and decompression exposed as Read/BufRead/Write streams. Supports miniz_oxide, miniz.c, and multiple zlib implementations. Supports zlib, gzip, and raw deflate streams. """ [workspace] members = ['systest'] [dependencies] libc = "0.2.65" cfg-if = "1.0.0" miniz-sys = { path = "miniz-sys", version = "0.1.11", optional = true } libz-sys = { version = "1.1.0", optional = true, default-features = false } cloudflare-zlib-sys = { version = "0.3.0", optional = true } tokio-io = { version = "0.1.11", optional = true } futures = { version = "0.1.25", optional = true } miniz_oxide = { version = "0.4.0", optional = true, default-features = false } crc32fast = "1.2.0" [target.'cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))'.dependencies] miniz_oxide = { version = "0.4.0", default-features = false } [dev-dependencies] rand = "0.7" quickcheck = { version = "0.9", default-features = false } tokio-io = "0.1.11" tokio-tcp = "0.1.3" tokio-threadpool = "0.1.10" futures = "0.1" [features] default = ["rust_backend"] any_zlib = [] # note: this is not a real user-facing feature zlib = ["any_zlib", "libz-sys"] zlib-ng-compat = ["zlib", "libz-sys/zlib-ng"] cloudflare_zlib = ["any_zlib", "cloudflare-zlib-sys"] rust_backend = ["miniz_oxide"] tokio = ["tokio-io", "futures"] flate2-1.0.22/LICENSE-APACHE000064400000000000000000000251370072674642500130470ustar 00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. flate2-1.0.22/LICENSE-MIT000064400000000000000000000020410072674642500125440ustar 00000000000000Copyright (c) 2014 Alex Crichton Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. flate2-1.0.22/README.md000064400000000000000000000062440072674642500124000ustar 00000000000000# flate2 [![Crates.io](https://img.shields.io/crates/v/flate2.svg?maxAge=2592000)](https://crates.io/crates/flate2) [![Documentation](https://docs.rs/flate2/badge.svg)](https://docs.rs/flate2) A streaming compression/decompression library DEFLATE-based streams in Rust. This crate by default uses the `miniz_oxide` crate, a port of `miniz.c` to pure Rust. This crate also supports other [backends](#Backends), such as the widely available zlib library or the high-performance zlib-ng library. Supported formats: * deflate * zlib * gzip ```toml # Cargo.toml [dependencies] flate2 = "1.0" ``` ## Compression ```rust use std::io::prelude::*; use flate2::Compression; use flate2::write::ZlibEncoder; fn main() { let mut e = ZlibEncoder::new(Vec::new(), Compression::default()); e.write_all(b"foo"); e.write_all(b"bar"); let compressed_bytes = e.finish(); } ``` ## Decompression ```rust,no_run use std::io::prelude::*; use flate2::read::GzDecoder; fn main() { let mut d = GzDecoder::new("...".as_bytes()); let mut s = String::new(); d.read_to_string(&mut s).unwrap(); println!("{}", s); } ``` ## Backends The default `miniz_oxide` backend has the advantage of being pure Rust, but if you're already using zlib with another C library, for example, you can use that for Rust code as well: ```toml [dependencies] flate2 = { version = "1.0.17", features = ["zlib"], default-features = false } ``` This supports either the high-performance zlib-ng backend (in zlib-compat mode) or the use of a shared system zlib library. To explicitly opt into the fast zlib-ng backend, use: ```toml [dependencies] flate2 = { version = "1.0.17", features = ["zlib-ng-compat"], default-features = false } ``` Note that if any crate in your dependency graph explicitly requests stock zlib, or uses libz-sys directly without `default-features = false`, you'll get stock zlib rather than zlib-ng. See [the libz-sys README](https://github.com/rust-lang/libz-sys/blob/main/README.md) for details. For compatibility with previous versions of `flate2`, the cloudflare optimized version of zlib is available, via the `cloudflare_zlib` feature. It's not as fast as zlib-ng, but it's faster than stock zlib. It requires a x86-64 CPU with SSE 4.2 or ARM64 with NEON & CRC. It does not support 32-bit CPUs at all and is incompatible with mingw. For more information check the [crate documentation](https://crates.io/crates/cloudflare-zlib-sys). Note that `cloudflare_zlib` will cause breakage if any other crate in your crate graph uses another version of zlib/libz. For compatibility with previous versions of `flate2`, the C version of `miniz.c` is still available, using the feature `miniz-sys`. # License This project is licensed under either of * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) at your option. ### Contribution Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this project by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. flate2-1.0.22/examples/compress_file.rs000064400000000000000000000015350072674642500161350ustar 00000000000000extern crate flate2; use flate2::write::GzEncoder; use flate2::Compression; use std::env::args; use std::fs::File; use std::io::copy; use std::io::BufReader; use std::time::Instant; fn main() { if args().len() != 3 { eprintln!("Usage: ./compress_file `source` `target`"); return; } let mut input = BufReader::new(File::open(args().nth(1).unwrap()).unwrap()); let output = File::create(args().nth(2).unwrap()).unwrap(); let mut encoder = GzEncoder::new(output, Compression::default()); let start = Instant::now(); copy(&mut input, &mut encoder).unwrap(); let output = encoder.finish().unwrap(); println!( "Source len: {:?}", input.get_ref().metadata().unwrap().len() ); println!("Target len: {:?}", output.metadata().unwrap().len()); println!("Elapsed: {:?}", start.elapsed()); } flate2-1.0.22/examples/deflatedecoder-bufread.rs000064400000000000000000000013470072674642500176440ustar 00000000000000extern crate flate2; use flate2::bufread::DeflateDecoder; use flate2::write::DeflateEncoder; use flate2::Compression; use std::io; use std::io::prelude::*; // Compress a sample string and print it after transformation. fn main() { let mut e = DeflateEncoder::new(Vec::new(), Compression::default()); e.write_all(b"Hello World").unwrap(); let bytes = e.finish().unwrap(); println!("{}", decode_reader(bytes).unwrap()); } // Uncompresses a Deflate Encoded vector of bytes and returns a string or error // Here &[u8] implements Read fn decode_reader(bytes: Vec) -> io::Result { let mut deflater = DeflateDecoder::new(&bytes[..]); let mut s = String::new(); deflater.read_to_string(&mut s)?; Ok(s) } flate2-1.0.22/examples/deflatedecoder-read.rs000064400000000000000000000013440072674642500171440ustar 00000000000000extern crate flate2; use flate2::read::DeflateDecoder; use flate2::write::DeflateEncoder; use flate2::Compression; use std::io; use std::io::prelude::*; // Compress a sample string and print it after transformation. fn main() { let mut e = DeflateEncoder::new(Vec::new(), Compression::default()); e.write_all(b"Hello World").unwrap(); let bytes = e.finish().unwrap(); println!("{}", decode_reader(bytes).unwrap()); } // Uncompresses a Deflate Encoded vector of bytes and returns a string or error // Here &[u8] implements Read fn decode_reader(bytes: Vec) -> io::Result { let mut deflater = DeflateDecoder::new(&bytes[..]); let mut s = String::new(); deflater.read_to_string(&mut s)?; Ok(s) } flate2-1.0.22/examples/deflatedecoder-write.rs000064400000000000000000000015440072674642500173650ustar 00000000000000extern crate flate2; use flate2::write::DeflateDecoder; use flate2::write::DeflateEncoder; use flate2::Compression; use std::io; use std::io::prelude::*; // Compress a sample string and print it after transformation. fn main() { let mut e = DeflateEncoder::new(Vec::new(), Compression::default()); e.write_all(b"Hello World").unwrap(); let bytes = e.finish().unwrap(); println!("{}", decode_reader(bytes).unwrap()); } // Uncompresses a Deflate Encoded vector of bytes and returns a string or error // Here Vec implements Write fn decode_reader(bytes: Vec) -> io::Result { let mut writer = Vec::new(); let mut deflater = DeflateDecoder::new(writer); deflater.write_all(&bytes[..])?; writer = deflater.finish()?; let return_string = String::from_utf8(writer).expect("String parsing error"); Ok(return_string) } flate2-1.0.22/examples/deflateencoder-bufread.rs000064400000000000000000000013110072674642500176450ustar 00000000000000extern crate flate2; use flate2::bufread::DeflateEncoder; use flate2::Compression; use std::fs::File; use std::io; use std::io::prelude::*; use std::io::BufReader; // Open file and debug print the contents compressed with Deflate fn main() { println!("{:?}", open_hello_world().unwrap()); } // Opens sample file, compresses the contents and returns a Vector or error // File wrapped in a BufReader implements Bufread fn open_hello_world() -> io::Result> { let f = File::open("examples/hello_world.txt")?; let b = BufReader::new(f); let mut deflater = DeflateEncoder::new(b, Compression::fast()); let mut buffer = Vec::new(); deflater.read_to_end(&mut buffer)?; Ok(buffer) } flate2-1.0.22/examples/deflateencoder-read.rs000064400000000000000000000011200072674642500171460ustar 00000000000000extern crate flate2; use flate2::read::DeflateEncoder; use flate2::Compression; use std::io; use std::io::prelude::*; // Print the Deflate compressed representation of hello world fn main() { println!("{:?}", deflateencoder_read_hello_world().unwrap()); } // Return a vector containing the Defalte compressed version of hello world fn deflateencoder_read_hello_world() -> io::Result> { let mut result = Vec::new(); let c = b"hello world"; let mut deflater = DeflateEncoder::new(&c[..], Compression::fast()); deflater.read_to_end(&mut result)?; Ok(result) } flate2-1.0.22/examples/deflateencoder-write.rs000064400000000000000000000005430072674642500173750ustar 00000000000000extern crate flate2; use flate2::write::DeflateEncoder; use flate2::Compression; use std::io::prelude::*; // Vec implements Write to print the compressed bytes of sample string fn main() { let mut e = DeflateEncoder::new(Vec::new(), Compression::default()); e.write_all(b"Hello World").unwrap(); println!("{:?}", e.finish().unwrap()); } flate2-1.0.22/examples/gzbuilder.rs000064400000000000000000000011760072674642500152730ustar 00000000000000extern crate flate2; use flate2::Compression; use flate2::GzBuilder; use std::fs::File; use std::io; use std::io::prelude::*; // Open file and debug print the contents compressed with gzip fn main() { sample_builder().unwrap(); } // GzBuilder opens a file and writes a sample string using Builder pattern fn sample_builder() -> Result<(), io::Error> { let f = File::create("examples/hello_world.gz")?; let mut gz = GzBuilder::new() .filename("hello_world.txt") .comment("test file, please delete") .write(f, Compression::default()); gz.write_all(b"hello world")?; gz.finish()?; Ok(()) } flate2-1.0.22/examples/gzdecoder-bufread.rs000064400000000000000000000013050072674642500166520ustar 00000000000000extern crate flate2; use flate2::bufread::GzDecoder; use flate2::write::GzEncoder; use flate2::Compression; use std::io; use std::io::prelude::*; // Compress a sample string and print it after transformation. fn main() { let mut e = GzEncoder::new(Vec::new(), Compression::default()); e.write_all(b"Hello World").unwrap(); let bytes = e.finish().unwrap(); println!("{}", decode_reader(bytes).unwrap()); } // Uncompresses a Gz Encoded vector of bytes and returns a string or error // Here &[u8] implements BufRead fn decode_reader(bytes: Vec) -> io::Result { let mut gz = GzDecoder::new(&bytes[..]); let mut s = String::new(); gz.read_to_string(&mut s)?; Ok(s) } flate2-1.0.22/examples/gzdecoder-read.rs000064400000000000000000000012770072674642500161650ustar 00000000000000extern crate flate2; use flate2::read::GzDecoder; use flate2::write::GzEncoder; use flate2::Compression; use std::io; use std::io::prelude::*; // Compress a sample string and print it after transformation. fn main() { let mut e = GzEncoder::new(Vec::new(), Compression::default()); e.write_all(b"Hello World").unwrap(); let bytes = e.finish().unwrap(); println!("{}", decode_reader(bytes).unwrap()); } // Uncompresses a Gz Encoded vector of bytes and returns a string or error // Here &[u8] implements Read fn decode_reader(bytes: Vec) -> io::Result { let mut gz = GzDecoder::new(&bytes[..]); let mut s = String::new(); gz.read_to_string(&mut s)?; Ok(s) } flate2-1.0.22/examples/gzdecoder-write.rs000064400000000000000000000015170072674642500164010ustar 00000000000000extern crate flate2; use flate2::write::{GzDecoder, GzEncoder}; use flate2::Compression; use std::io; use std::io::prelude::*; // Compress a sample string and print it after transformation. fn main() { let mut e = GzEncoder::new(Vec::new(), Compression::default()); e.write_all(b"Hello World").unwrap(); let bytes = e.finish().unwrap(); println!("{}", decode_writer(bytes).unwrap()); } // Uncompresses a Gz Encoded vector of bytes and returns a string or error // Here &[u8] implements Read fn decode_writer(bytes: Vec) -> io::Result { let mut writer = Vec::new(); let mut decoder = GzDecoder::new(writer); decoder.write_all(&bytes[..])?; decoder.try_finish()?; writer = decoder.finish()?; let return_string = String::from_utf8(writer).expect("String parsing error"); Ok(return_string) } flate2-1.0.22/examples/gzencoder-bufread.rs000064400000000000000000000012600072674642500166640ustar 00000000000000extern crate flate2; use flate2::bufread::GzEncoder; use flate2::Compression; use std::fs::File; use std::io; use std::io::prelude::*; use std::io::BufReader; // Open file and debug print the contents compressed with gzip fn main() { println!("{:?}", open_hello_world().unwrap()); } // Opens sample file, compresses the contents and returns a Vector or error // File wrapped in a BufReader implements Bufread fn open_hello_world() -> io::Result> { let f = File::open("examples/hello_world.txt")?; let b = BufReader::new(f); let mut gz = GzEncoder::new(b, Compression::fast()); let mut buffer = Vec::new(); gz.read_to_end(&mut buffer)?; Ok(buffer) } flate2-1.0.22/examples/gzencoder-read.rs000064400000000000000000000010440072674642500161670ustar 00000000000000extern crate flate2; use flate2::read::GzEncoder; use flate2::Compression; use std::io; use std::io::prelude::*; // Print the GZ compressed representation of hello world fn main() { println!("{:?}", gzencoder_read_hello_world().unwrap()); } // Return a vector containing the GZ compressed version of hello world fn gzencoder_read_hello_world() -> io::Result> { let mut result = Vec::new(); let c = b"hello world"; let mut z = GzEncoder::new(&c[..], Compression::fast()); z.read_to_end(&mut result)?; Ok(result) } flate2-1.0.22/examples/gzencoder-write.rs000064400000000000000000000005310072674642500164060ustar 00000000000000extern crate flate2; use flate2::write::GzEncoder; use flate2::Compression; use std::io::prelude::*; // Vec implements Write to print the compressed bytes of sample string fn main() { let mut e = GzEncoder::new(Vec::new(), Compression::default()); e.write_all(b"Hello World").unwrap(); println!("{:?}", e.finish().unwrap()); } flate2-1.0.22/examples/gzmultidecoder-bufread.rs000064400000000000000000000013170072674642500177300ustar 00000000000000extern crate flate2; use flate2::bufread::MultiGzDecoder; use flate2::write::GzEncoder; use flate2::Compression; use std::io; use std::io::prelude::*; // Compress a sample string and print it after transformation. fn main() { let mut e = GzEncoder::new(Vec::new(), Compression::default()); e.write_all(b"Hello World").unwrap(); let bytes = e.finish().unwrap(); println!("{}", decode_reader(bytes).unwrap()); } // Uncompresses a Gz Encoded vector of bytes and returns a string or error // Here &[u8] implements BufRead fn decode_reader(bytes: Vec) -> io::Result { let mut gz = MultiGzDecoder::new(&bytes[..]); let mut s = String::new(); gz.read_to_string(&mut s)?; Ok(s) } flate2-1.0.22/examples/gzmultidecoder-read.rs000064400000000000000000000013110072674642500172250ustar 00000000000000extern crate flate2; use flate2::read::MultiGzDecoder; use flate2::write::GzEncoder; use flate2::Compression; use std::io; use std::io::prelude::*; // Compress a sample string and print it after transformation. fn main() { let mut e = GzEncoder::new(Vec::new(), Compression::default()); e.write_all(b"Hello World").unwrap(); let bytes = e.finish().unwrap(); println!("{}", decode_reader(bytes).unwrap()); } // Uncompresses a Gz Encoded vector of bytes and returns a string or error // Here &[u8] implements Read fn decode_reader(bytes: Vec) -> io::Result { let mut gz = MultiGzDecoder::new(&bytes[..]); let mut s = String::new(); gz.read_to_string(&mut s)?; Ok(s) } flate2-1.0.22/examples/hello_world.txt000064400000000000000000000000140072674642500157770ustar 00000000000000Hello World flate2-1.0.22/examples/zlibdecoder-bufread.rs000064400000000000000000000013230072674642500171720ustar 00000000000000extern crate flate2; use flate2::bufread::ZlibDecoder; use flate2::write::ZlibEncoder; use flate2::Compression; use std::io; use std::io::prelude::*; // Compress a sample string and print it after transformation. fn main() { let mut e = ZlibEncoder::new(Vec::new(), Compression::default()); e.write_all(b"Hello World").unwrap(); let bytes = e.finish().unwrap(); println!("{}", decode_bufreader(bytes).unwrap()); } // Uncompresses a Zlib Encoded vector of bytes and returns a string or error // Here &[u8] implements BufRead fn decode_bufreader(bytes: Vec) -> io::Result { let mut z = ZlibDecoder::new(&bytes[..]); let mut s = String::new(); z.read_to_string(&mut s)?; Ok(s) } flate2-1.0.22/examples/zlibdecoder-read.rs000064400000000000000000000013070072674642500164770ustar 00000000000000extern crate flate2; use flate2::read::ZlibDecoder; use flate2::write::ZlibEncoder; use flate2::Compression; use std::io; use std::io::prelude::*; // Compress a sample string and print it after transformation. fn main() { let mut e = ZlibEncoder::new(Vec::new(), Compression::default()); e.write_all(b"Hello World").unwrap(); let bytes = e.finish().unwrap(); println!("{}", decode_reader(bytes).unwrap()); } // Uncompresses a Zlib Encoded vector of bytes and returns a string or error // Here &[u8] implements Read fn decode_reader(bytes: Vec) -> io::Result { let mut z = ZlibDecoder::new(&bytes[..]); let mut s = String::new(); z.read_to_string(&mut s)?; Ok(s) } flate2-1.0.22/examples/zlibdecoder-write.rs000064400000000000000000000015000072674642500167110ustar 00000000000000extern crate flate2; use flate2::write::ZlibDecoder; use flate2::write::ZlibEncoder; use flate2::Compression; use std::io; use std::io::prelude::*; // Compress a sample string and print it after transformation. fn main() { let mut e = ZlibEncoder::new(Vec::new(), Compression::default()); e.write_all(b"Hello World").unwrap(); let bytes = e.finish().unwrap(); println!("{}", decode_reader(bytes).unwrap()); } // Uncompresses a Zlib Encoded vector of bytes and returns a string or error // Here Vec implements Write fn decode_reader(bytes: Vec) -> io::Result { let mut writer = Vec::new(); let mut z = ZlibDecoder::new(writer); z.write_all(&bytes[..])?; writer = z.finish()?; let return_string = String::from_utf8(writer).expect("String parsing error"); Ok(return_string) } flate2-1.0.22/examples/zlibencoder-bufread.rs000064400000000000000000000012620072674642500172060ustar 00000000000000extern crate flate2; use flate2::bufread::ZlibEncoder; use flate2::Compression; use std::fs::File; use std::io; use std::io::prelude::*; use std::io::BufReader; // Open file and debug print the contents compressed with zlib fn main() { println!("{:?}", open_hello_world().unwrap()); } // Opens sample file, compresses the contents and returns a Vector or error // File wrapped in a BufReader implements Bufread fn open_hello_world() -> io::Result> { let f = File::open("examples/hello_world.txt")?; let b = BufReader::new(f); let mut z = ZlibEncoder::new(b, Compression::fast()); let mut buffer = Vec::new(); z.read_to_end(&mut buffer)?; Ok(buffer) } flate2-1.0.22/examples/zlibencoder-read.rs000064400000000000000000000011140072674642500165050ustar 00000000000000extern crate flate2; use flate2::read::ZlibEncoder; use flate2::Compression; use std::fs::File; use std::io::prelude::*; // Open file and debug print the compressed contents fn main() { println!("{:?}", open_hello_world().unwrap()); } // Opens sample file, compresses the contents and returns a Vector or error // File implements Read 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 result = Vec::new(); z.read_to_end(&mut result)?; Ok(result) } flate2-1.0.22/examples/zlibencoder-write.rs000064400000000000000000000005350072674642500167320ustar 00000000000000extern crate flate2; use flate2::write::ZlibEncoder; use flate2::Compression; use std::io::prelude::*; // Vec implements Write to print the compressed bytes of sample string fn main() { let mut e = ZlibEncoder::new(Vec::new(), Compression::default()); e.write_all(b"Hello World").unwrap(); println!("{:?}", e.finish().unwrap()); } flate2-1.0.22/src/bufreader.rs000064400000000000000000000053520072674642500142140ustar 00000000000000// Copyright 2013 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. use std::cmp; use std::io; use std::io::prelude::*; use std::mem; pub struct BufReader { inner: R, buf: Box<[u8]>, pos: usize, cap: usize, } impl ::std::fmt::Debug for BufReader where R: ::std::fmt::Debug, { fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> { fmt.debug_struct("BufReader") .field("reader", &self.inner) .field( "buffer", &format_args!("{}/{}", self.cap - self.pos, self.buf.len()), ) .finish() } } impl BufReader { pub fn new(inner: R) -> BufReader { BufReader::with_buf(vec![0; 32 * 1024], inner) } pub fn with_buf(buf: Vec, inner: R) -> BufReader { BufReader { inner: inner, buf: buf.into_boxed_slice(), pos: 0, cap: 0, } } } impl BufReader { pub fn get_ref(&self) -> &R { &self.inner } pub fn get_mut(&mut self) -> &mut R { &mut self.inner } pub fn into_inner(self) -> R { self.inner } pub fn reset(&mut self, inner: R) -> R { self.pos = 0; self.cap = 0; mem::replace(&mut self.inner, inner) } } impl Read for BufReader { fn read(&mut self, buf: &mut [u8]) -> io::Result { // If we don't have any buffered data and we're doing a massive read // (larger than our internal buffer), bypass our internal buffer // entirely. if self.pos == self.cap && buf.len() >= self.buf.len() { return self.inner.read(buf); } let nread = { let mut rem = self.fill_buf()?; rem.read(buf)? }; self.consume(nread); Ok(nread) } } impl BufRead for BufReader { fn fill_buf(&mut self) -> io::Result<&[u8]> { // If we've reached the end of our internal buffer then we need to fetch // some more data from the underlying reader. if self.pos == self.cap { self.cap = self.inner.read(&mut self.buf)?; self.pos = 0; } Ok(&self.buf[self.pos..self.cap]) } fn consume(&mut self, amt: usize) { self.pos = cmp::min(self.pos + amt, self.cap); } } flate2-1.0.22/src/crc.rs000064400000000000000000000100320072674642500130130ustar 00000000000000//! Simple CRC bindings backed by miniz.c use std::io; use std::io::prelude::*; use crc32fast::Hasher; /// The CRC calculated by a [`CrcReader`]. /// /// [`CrcReader`]: struct.CrcReader.html #[derive(Debug)] pub struct Crc { amt: u32, hasher: Hasher, } /// A wrapper around a [`Read`] that calculates the CRC. /// /// [`Read`]: https://doc.rust-lang.org/std/io/trait.Read.html #[derive(Debug)] pub struct CrcReader { inner: R, crc: Crc, } impl Crc { /// Create a new CRC. pub fn new() -> Crc { Crc { amt: 0, hasher: Hasher::new(), } } /// Returns the current crc32 checksum. pub fn sum(&self) -> u32 { self.hasher.clone().finalize() } /// The number of bytes that have been used to calculate the CRC. /// This value is only accurate if the amount is lower than 232. pub fn amount(&self) -> u32 { self.amt } /// Update the CRC with the bytes in `data`. pub fn update(&mut self, data: &[u8]) { self.amt = self.amt.wrapping_add(data.len() as u32); self.hasher.update(data); } /// Reset the CRC. pub fn reset(&mut self) { self.amt = 0; self.hasher.reset(); } /// Combine the CRC with the CRC for the subsequent block of bytes. pub fn combine(&mut self, additional_crc: &Crc) { self.amt += additional_crc.amt; self.hasher.combine(&additional_crc.hasher); } } impl CrcReader { /// Create a new CrcReader. pub fn new(r: R) -> CrcReader { CrcReader { inner: r, crc: Crc::new(), } } } impl CrcReader { /// Get the Crc for this CrcReader. pub fn crc(&self) -> &Crc { &self.crc } /// Get the reader that is wrapped by this CrcReader. pub fn into_inner(self) -> R { self.inner } /// Get the reader that is wrapped by this CrcReader by reference. pub fn get_ref(&self) -> &R { &self.inner } /// Get a mutable reference to the reader that is wrapped by this CrcReader. pub fn get_mut(&mut self) -> &mut R { &mut self.inner } /// Reset the Crc in this CrcReader. pub fn reset(&mut self) { self.crc.reset(); } } impl Read for CrcReader { fn read(&mut self, into: &mut [u8]) -> io::Result { let amt = self.inner.read(into)?; self.crc.update(&into[..amt]); Ok(amt) } } impl BufRead for CrcReader { fn fill_buf(&mut self) -> io::Result<&[u8]> { self.inner.fill_buf() } fn consume(&mut self, amt: usize) { if let Ok(data) = self.inner.fill_buf() { self.crc.update(&data[..amt]); } self.inner.consume(amt); } } /// A wrapper around a [`Write`] that calculates the CRC. /// /// [`Write`]: https://doc.rust-lang.org/std/io/trait.Write.html #[derive(Debug)] pub struct CrcWriter { inner: W, crc: Crc, } impl CrcWriter { /// Get the Crc for this CrcWriter. pub fn crc(&self) -> &Crc { &self.crc } /// Get the writer that is wrapped by this CrcWriter. pub fn into_inner(self) -> W { self.inner } /// Get the writer that is wrapped by this CrcWriter by reference. pub fn get_ref(&self) -> &W { &self.inner } /// Get a mutable reference to the writer that is wrapped by this CrcWriter. pub fn get_mut(&mut self) -> &mut W { &mut self.inner } /// Reset the Crc in this CrcWriter. pub fn reset(&mut self) { self.crc.reset(); } } impl CrcWriter { /// Create a new CrcWriter. pub fn new(w: W) -> CrcWriter { CrcWriter { inner: w, crc: Crc::new(), } } } impl Write for CrcWriter { fn write(&mut self, buf: &[u8]) -> io::Result { let amt = self.inner.write(buf)?; self.crc.update(&buf[..amt]); Ok(amt) } fn flush(&mut self) -> io::Result<()> { self.inner.flush() } } flate2-1.0.22/src/deflate/bufread.rs000064400000000000000000000172120072674642500152670ustar 00000000000000use std::io; use std::io::prelude::*; use std::mem; #[cfg(feature = "tokio")] use futures::Poll; #[cfg(feature = "tokio")] use tokio_io::{AsyncRead, AsyncWrite}; use crate::zio; use crate::{Compress, Decompress}; /// A DEFLATE encoder, or compressor. /// /// This structure consumes a [`BufRead`] interface, reading uncompressed data /// from the underlying reader, and emitting compressed data. /// /// [`BufRead`]: https://doc.rust-lang.org/std/io/trait.BufRead.html /// /// # Examples /// /// ``` /// use std::io::prelude::*; /// use std::io; /// use flate2::Compression; /// use flate2::bufread::DeflateEncoder; /// use std::fs::File; /// use std::io::BufReader; /// /// # fn main() { /// # println!("{:?}", open_hello_world().unwrap()); /// # } /// # /// // Opens sample file, compresses the contents and returns a Vector /// fn open_hello_world() -> io::Result> { /// let f = File::open("examples/hello_world.txt")?; /// let b = BufReader::new(f); /// let mut deflater = DeflateEncoder::new(b, Compression::fast()); /// let mut buffer = Vec::new(); /// deflater.read_to_end(&mut buffer)?; /// Ok(buffer) /// } /// ``` #[derive(Debug)] pub struct DeflateEncoder { obj: R, data: Compress, } impl DeflateEncoder { /// Creates a new encoder which will read uncompressed data from the given /// stream and emit the compressed stream. pub fn new(r: R, level: crate::Compression) -> DeflateEncoder { DeflateEncoder { obj: r, data: Compress::new(level, false), } } } pub fn reset_encoder_data(zlib: &mut DeflateEncoder) { zlib.data.reset(); } impl DeflateEncoder { /// Resets the state of this encoder entirely, swapping out the input /// stream for another. /// /// This function will reset the internal state of this encoder and replace /// the input stream with the one provided, returning the previous input /// stream. Future data read from this encoder will be the compressed /// version of `r`'s data. pub fn reset(&mut self, r: R) -> R { reset_encoder_data(self); mem::replace(&mut self.obj, r) } /// Acquires a reference to the underlying reader pub fn get_ref(&self) -> &R { &self.obj } /// Acquires a mutable reference to the underlying stream /// /// Note that mutation of the stream may result in surprising results if /// this encoder is continued to be used. pub fn get_mut(&mut self) -> &mut R { &mut self.obj } /// Consumes this encoder, returning the underlying reader. pub fn into_inner(self) -> R { self.obj } /// Returns the number of bytes that have been read into this compressor. /// /// Note that not all bytes read from the underlying object may be accounted /// for, there may still be some active buffering. pub fn total_in(&self) -> u64 { self.data.total_in() } /// Returns the number of bytes that the compressor has produced. /// /// Note that not all bytes may have been read yet, some may still be /// buffered. pub fn total_out(&self) -> u64 { self.data.total_out() } } impl Read for DeflateEncoder { fn read(&mut self, buf: &mut [u8]) -> io::Result { zio::read(&mut self.obj, &mut self.data, buf) } } #[cfg(feature = "tokio")] impl AsyncRead for DeflateEncoder {} impl Write for DeflateEncoder { fn write(&mut self, buf: &[u8]) -> io::Result { self.get_mut().write(buf) } fn flush(&mut self) -> io::Result<()> { self.get_mut().flush() } } #[cfg(feature = "tokio")] impl AsyncWrite for DeflateEncoder { fn shutdown(&mut self) -> Poll<(), io::Error> { self.get_mut().shutdown() } } /// A DEFLATE decoder, or decompressor. /// /// This structure consumes a [`BufRead`] interface, reading compressed data /// from the underlying reader, and emitting uncompressed data. /// /// [`BufRead`]: https://doc.rust-lang.org/std/io/trait.BufRead.html /// /// # Examples /// /// ``` /// use std::io::prelude::*; /// use std::io; /// # use flate2::Compression; /// # use flate2::write::DeflateEncoder; /// use flate2::bufread::DeflateDecoder; /// /// # fn main() { /// # let mut e = DeflateEncoder::new(Vec::new(), Compression::default()); /// # e.write_all(b"Hello World").unwrap(); /// # let bytes = e.finish().unwrap(); /// # println!("{}", decode_reader(bytes).unwrap()); /// # } /// // Uncompresses a Deflate Encoded vector of bytes and returns a string or error /// // Here &[u8] implements Read /// fn decode_reader(bytes: Vec) -> io::Result { /// let mut deflater = DeflateDecoder::new(&bytes[..]); /// let mut s = String::new(); /// deflater.read_to_string(&mut s)?; /// Ok(s) /// } /// ``` #[derive(Debug)] pub struct DeflateDecoder { obj: R, data: Decompress, } pub fn reset_decoder_data(zlib: &mut DeflateDecoder) { zlib.data = Decompress::new(false); } impl DeflateDecoder { /// Creates a new decoder which will decompress data read from the given /// stream. pub fn new(r: R) -> DeflateDecoder { DeflateDecoder { obj: r, data: Decompress::new(false), } } } impl DeflateDecoder { /// Resets the state of this decoder entirely, swapping out the input /// stream for another. /// /// This will reset the internal state of this decoder and replace the /// input stream with the one provided, returning the previous input /// stream. Future data read from this decoder will be the decompressed /// version of `r`'s data. pub fn reset(&mut self, r: R) -> R { reset_decoder_data(self); mem::replace(&mut self.obj, r) } /// Resets the state of this decoder's data /// /// This will reset the internal state of this decoder. It will continue /// reading from the same stream. pub fn reset_data(&mut self) { reset_decoder_data(self); } /// Acquires a reference to the underlying stream pub fn get_ref(&self) -> &R { &self.obj } /// Acquires a mutable reference to the underlying stream /// /// Note that mutation of the stream may result in surprising results if /// this encoder is continued to be used. pub fn get_mut(&mut self) -> &mut R { &mut self.obj } /// Consumes this decoder, returning the underlying reader. pub fn into_inner(self) -> R { self.obj } /// Returns the number of bytes that the decompressor has consumed. /// /// Note that this will likely be smaller than what the decompressor /// actually read from the underlying stream due to buffering. pub fn total_in(&self) -> u64 { self.data.total_in() } /// Returns the number of bytes that the decompressor has produced. pub fn total_out(&self) -> u64 { self.data.total_out() } } impl Read for DeflateDecoder { fn read(&mut self, into: &mut [u8]) -> io::Result { zio::read(&mut self.obj, &mut self.data, into) } } #[cfg(feature = "tokio")] impl AsyncRead for DeflateDecoder {} impl Write for DeflateDecoder { fn write(&mut self, buf: &[u8]) -> io::Result { self.get_mut().write(buf) } fn flush(&mut self) -> io::Result<()> { self.get_mut().flush() } } #[cfg(feature = "tokio")] impl AsyncWrite for DeflateDecoder { fn shutdown(&mut self) -> Poll<(), io::Error> { self.get_mut().shutdown() } } flate2-1.0.22/src/deflate/mod.rs000064400000000000000000000140670072674642500144430ustar 00000000000000pub mod bufread; pub mod read; pub mod write; #[cfg(test)] mod tests { use std::io::prelude::*; use rand::{thread_rng, Rng}; use super::{read, write}; use crate::Compression; #[test] fn roundtrip() { let mut real = Vec::new(); let mut w = write::DeflateEncoder::new(Vec::new(), Compression::default()); let v = crate::random_bytes().take(1024).collect::>(); for _ in 0..200 { let to_write = &v[..thread_rng().gen_range(0, v.len())]; real.extend(to_write.iter().map(|x| *x)); w.write_all(to_write).unwrap(); } let result = w.finish().unwrap(); let mut r = read::DeflateDecoder::new(&result[..]); let mut ret = Vec::new(); r.read_to_end(&mut ret).unwrap(); assert!(ret == real); } #[test] fn drop_writes() { let mut data = Vec::new(); write::DeflateEncoder::new(&mut data, Compression::default()) .write_all(b"foo") .unwrap(); let mut r = read::DeflateDecoder::new(&data[..]); let mut ret = Vec::new(); r.read_to_end(&mut ret).unwrap(); assert!(ret == b"foo"); } #[test] fn total_in() { let mut real = Vec::new(); let mut w = write::DeflateEncoder::new(Vec::new(), Compression::default()); let v = crate::random_bytes().take(1024).collect::>(); for _ in 0..200 { let to_write = &v[..thread_rng().gen_range(0, v.len())]; real.extend(to_write.iter().map(|x| *x)); w.write_all(to_write).unwrap(); } let mut result = w.finish().unwrap(); let result_len = result.len(); for _ in 0..200 { result.extend(v.iter().map(|x| *x)); } let mut r = read::DeflateDecoder::new(&result[..]); let mut ret = Vec::new(); r.read_to_end(&mut ret).unwrap(); assert!(ret == real); assert_eq!(r.total_in(), result_len as u64); } #[test] fn roundtrip2() { let v = crate::random_bytes().take(1024 * 1024).collect::>(); let mut r = read::DeflateDecoder::new(read::DeflateEncoder::new(&v[..], Compression::default())); let mut ret = Vec::new(); r.read_to_end(&mut ret).unwrap(); assert_eq!(ret, v); } #[test] fn roundtrip3() { let v = crate::random_bytes().take(1024 * 1024).collect::>(); let mut w = write::DeflateEncoder::new( write::DeflateDecoder::new(Vec::new()), Compression::default(), ); w.write_all(&v).unwrap(); let w = w.finish().unwrap().finish().unwrap(); assert!(w == v); } #[test] fn reset_writer() { let v = crate::random_bytes().take(1024 * 1024).collect::>(); let mut w = write::DeflateEncoder::new(Vec::new(), Compression::default()); w.write_all(&v).unwrap(); let a = w.reset(Vec::new()).unwrap(); w.write_all(&v).unwrap(); let b = w.finish().unwrap(); let mut w = write::DeflateEncoder::new(Vec::new(), Compression::default()); w.write_all(&v).unwrap(); let c = w.finish().unwrap(); assert!(a == b && b == c); } #[test] fn reset_reader() { let v = crate::random_bytes().take(1024 * 1024).collect::>(); let (mut a, mut b, mut c) = (Vec::new(), Vec::new(), Vec::new()); let mut r = read::DeflateEncoder::new(&v[..], Compression::default()); r.read_to_end(&mut a).unwrap(); r.reset(&v[..]); r.read_to_end(&mut b).unwrap(); let mut r = read::DeflateEncoder::new(&v[..], Compression::default()); r.read_to_end(&mut c).unwrap(); assert!(a == b && b == c); } #[test] fn reset_decoder() { let v = crate::random_bytes().take(1024 * 1024).collect::>(); let mut w = write::DeflateEncoder::new(Vec::new(), Compression::default()); w.write_all(&v).unwrap(); let data = w.finish().unwrap(); { let (mut a, mut b, mut c) = (Vec::new(), Vec::new(), Vec::new()); let mut r = read::DeflateDecoder::new(&data[..]); r.read_to_end(&mut a).unwrap(); r.reset(&data); r.read_to_end(&mut b).unwrap(); let mut r = read::DeflateDecoder::new(&data[..]); r.read_to_end(&mut c).unwrap(); assert!(a == b && b == c && c == v); } { let mut w = write::DeflateDecoder::new(Vec::new()); w.write_all(&data).unwrap(); let a = w.reset(Vec::new()).unwrap(); w.write_all(&data).unwrap(); let b = w.finish().unwrap(); let mut w = write::DeflateDecoder::new(Vec::new()); w.write_all(&data).unwrap(); let c = w.finish().unwrap(); assert!(a == b && b == c && c == v); } } #[test] fn zero_length_read_with_data() { let m = vec![3u8; 128 * 1024 + 1]; let mut c = read::DeflateEncoder::new(&m[..], Compression::default()); let mut result = Vec::new(); c.read_to_end(&mut result).unwrap(); let mut d = read::DeflateDecoder::new(&result[..]); let mut data = Vec::new(); assert!(d.read(&mut data).unwrap() == 0); } #[test] fn qc_reader() { ::quickcheck::quickcheck(test as fn(_) -> _); fn test(v: Vec) -> bool { let mut r = read::DeflateDecoder::new(read::DeflateEncoder::new( &v[..], Compression::default(), )); let mut v2 = Vec::new(); r.read_to_end(&mut v2).unwrap(); v == v2 } } #[test] fn qc_writer() { ::quickcheck::quickcheck(test as fn(_) -> _); fn test(v: Vec) -> bool { let mut w = write::DeflateEncoder::new( write::DeflateDecoder::new(Vec::new()), Compression::default(), ); w.write_all(&v).unwrap(); v == w.finish().unwrap().finish().unwrap() } } } flate2-1.0.22/src/deflate/read.rs000064400000000000000000000205160072674642500145730ustar 00000000000000use std::io; use std::io::prelude::*; #[cfg(feature = "tokio")] use futures::Poll; #[cfg(feature = "tokio")] use tokio_io::{AsyncRead, AsyncWrite}; use super::bufread; use crate::bufreader::BufReader; /// A DEFLATE encoder, or compressor. /// /// This structure implements a [`Read`] interface and will read uncompressed /// data from an underlying stream and emit a stream of compressed data. /// /// [`Read`]: https://doc.rust-lang.org/std/io/trait.Read.html /// /// # Examples /// /// ``` /// use std::io::prelude::*; /// use std::io; /// use flate2::Compression; /// use flate2::read::DeflateEncoder; /// /// # fn main() { /// # println!("{:?}", deflateencoder_read_hello_world().unwrap()); /// # } /// # /// // 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 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()) /// } /// ``` #[derive(Debug)] pub struct DeflateEncoder { inner: bufread::DeflateEncoder>, } impl DeflateEncoder { /// Creates a new encoder which will read uncompressed data from the given /// stream and emit the compressed stream. pub fn new(r: R, level: crate::Compression) -> DeflateEncoder { DeflateEncoder { inner: bufread::DeflateEncoder::new(BufReader::new(r), level), } } } impl DeflateEncoder { /// Resets the state of this encoder entirely, swapping out the input /// stream for another. /// /// This function will reset the internal state of this encoder and replace /// the input stream with the one provided, returning the previous input /// stream. Future data read from this encoder will be the compressed /// version of `r`'s data. /// /// Note that there may be currently buffered data when this function is /// called, and in that case the buffered data is discarded. pub fn reset(&mut self, r: R) -> R { super::bufread::reset_encoder_data(&mut self.inner); self.inner.get_mut().reset(r) } /// Acquires a reference to the underlying reader pub fn get_ref(&self) -> &R { self.inner.get_ref().get_ref() } /// Acquires a mutable reference to the underlying stream /// /// Note that mutation of the stream may result in surprising results if /// this encoder is continued to be used. pub fn get_mut(&mut self) -> &mut R { self.inner.get_mut().get_mut() } /// Consumes this encoder, returning the underlying reader. /// /// Note that there may be buffered bytes which are not re-acquired as part /// of this transition. It's recommended to only call this function after /// EOF has been reached. pub fn into_inner(self) -> R { self.inner.into_inner().into_inner() } /// Returns the number of bytes that have been read into this compressor. /// /// Note that not all bytes read from the underlying object may be accounted /// for, there may still be some active buffering. pub fn total_in(&self) -> u64 { self.inner.total_in() } /// Returns the number of bytes that the compressor has produced. /// /// Note that not all bytes may have been read yet, some may still be /// buffered. pub fn total_out(&self) -> u64 { self.inner.total_out() } } impl Read for DeflateEncoder { fn read(&mut self, buf: &mut [u8]) -> io::Result { self.inner.read(buf) } } #[cfg(feature = "tokio")] impl AsyncRead for DeflateEncoder {} impl Write for DeflateEncoder { fn write(&mut self, buf: &[u8]) -> io::Result { self.get_mut().write(buf) } fn flush(&mut self) -> io::Result<()> { self.get_mut().flush() } } #[cfg(feature = "tokio")] impl AsyncWrite for DeflateEncoder { fn shutdown(&mut self) -> Poll<(), io::Error> { self.get_mut().shutdown() } } /// A DEFLATE decoder, or decompressor. /// /// This structure implements a [`Read`] interface and takes a stream of /// compressed data as input, providing the decompressed data when read from. /// /// [`Read`]: https://doc.rust-lang.org/std/io/trait.Read.html /// /// # Examples /// /// ``` /// use std::io::prelude::*; /// use std::io; /// # use flate2::Compression; /// # use flate2::write::DeflateEncoder; /// use flate2::read::DeflateDecoder; /// /// # fn main() { /// # let mut e = DeflateEncoder::new(Vec::new(), Compression::default()); /// # e.write_all(b"Hello World").unwrap(); /// # let bytes = e.finish().unwrap(); /// # println!("{}", decode_reader(bytes).unwrap()); /// # } /// // Uncompresses a Deflate Encoded vector of bytes and returns a string or error /// // Here &[u8] implements Read /// fn decode_reader(bytes: Vec) -> io::Result { /// let mut deflater = DeflateDecoder::new(&bytes[..]); /// let mut s = String::new(); /// deflater.read_to_string(&mut s)?; /// Ok(s) /// } /// ``` #[derive(Debug)] pub struct DeflateDecoder { inner: bufread::DeflateDecoder>, } impl DeflateDecoder { /// Creates a new decoder which will decompress data read from the given /// stream. pub fn new(r: R) -> DeflateDecoder { DeflateDecoder::new_with_buf(r, vec![0; 32 * 1024]) } /// Same as `new`, but the intermediate buffer for data is specified. /// /// Note that the capacity of the intermediate buffer is never increased, /// and it is recommended for it to be large. pub fn new_with_buf(r: R, buf: Vec) -> DeflateDecoder { DeflateDecoder { inner: bufread::DeflateDecoder::new(BufReader::with_buf(buf, r)), } } } impl DeflateDecoder { /// Resets the state of this decoder entirely, swapping out the input /// stream for another. /// /// This will reset the internal state of this decoder and replace the /// input stream with the one provided, returning the previous input /// stream. Future data read from this decoder will be the decompressed /// version of `r`'s data. /// /// Note that there may be currently buffered data when this function is /// called, and in that case the buffered data is discarded. pub fn reset(&mut self, r: R) -> R { super::bufread::reset_decoder_data(&mut self.inner); self.inner.get_mut().reset(r) } /// Acquires a reference to the underlying stream pub fn get_ref(&self) -> &R { self.inner.get_ref().get_ref() } /// Acquires a mutable reference to the underlying stream /// /// Note that mutation of the stream may result in surprising results if /// this encoder is continued to be used. pub fn get_mut(&mut self) -> &mut R { self.inner.get_mut().get_mut() } /// Consumes this decoder, returning the underlying reader. /// /// Note that there may be buffered bytes which are not re-acquired as part /// of this transition. It's recommended to only call this function after /// EOF has been reached. pub fn into_inner(self) -> R { self.inner.into_inner().into_inner() } /// Returns the number of bytes that the decompressor has consumed. /// /// Note that this will likely be smaller than what the decompressor /// actually read from the underlying stream due to buffering. pub fn total_in(&self) -> u64 { self.inner.total_in() } /// Returns the number of bytes that the decompressor has produced. pub fn total_out(&self) -> u64 { self.inner.total_out() } } impl Read for DeflateDecoder { fn read(&mut self, into: &mut [u8]) -> io::Result { self.inner.read(into) } } #[cfg(feature = "tokio")] impl AsyncRead for DeflateDecoder {} impl Write for DeflateDecoder { fn write(&mut self, buf: &[u8]) -> io::Result { self.get_mut().write(buf) } fn flush(&mut self) -> io::Result<()> { self.get_mut().flush() } } #[cfg(feature = "tokio")] impl AsyncWrite for DeflateDecoder { fn shutdown(&mut self) -> Poll<(), io::Error> { self.get_mut().shutdown() } } flate2-1.0.22/src/deflate/write.rs000064400000000000000000000272330072674642500150150ustar 00000000000000use std::io; use std::io::prelude::*; #[cfg(feature = "tokio")] use futures::Poll; #[cfg(feature = "tokio")] use tokio_io::{AsyncRead, AsyncWrite}; use crate::zio; use crate::{Compress, Decompress}; /// A DEFLATE encoder, or compressor. /// /// This structure implements a [`Write`] interface and takes a stream of /// uncompressed data, writing the compressed data to the wrapped writer. /// /// [`Write`]: https://doc.rust-lang.org/std/io/trait.Write.html /// /// # Examples /// /// ``` /// use std::io::prelude::*; /// use flate2::Compression; /// use flate2::write::DeflateEncoder; /// /// // Vec implements Write to print the compressed bytes of sample string /// # fn main() { /// /// let mut e = DeflateEncoder::new(Vec::new(), Compression::default()); /// e.write_all(b"Hello World").unwrap(); /// println!("{:?}", e.finish().unwrap()); /// # } /// ``` #[derive(Debug)] pub struct DeflateEncoder { inner: zio::Writer, } impl DeflateEncoder { /// Creates a new encoder which will write compressed data to the stream /// given at the given compression level. /// /// When this encoder is dropped or unwrapped the final pieces of data will /// be flushed. pub fn new(w: W, level: crate::Compression) -> DeflateEncoder { DeflateEncoder { inner: zio::Writer::new(w, Compress::new(level, false)), } } /// Acquires a reference to the underlying writer. pub fn get_ref(&self) -> &W { self.inner.get_ref() } /// Acquires a mutable reference to the underlying writer. /// /// Note that mutating the output/input state of the stream may corrupt this /// object, so care must be taken when using this method. pub fn get_mut(&mut self) -> &mut W { self.inner.get_mut() } /// Resets the state of this encoder entirely, swapping out the output /// stream for another. /// /// This function will finish encoding the current stream into the current /// output stream before swapping out the two output streams. If the stream /// cannot be finished an error is returned. /// /// After the current stream has been finished, this will reset the internal /// state of this encoder and replace the output stream with the one /// provided, returning the previous output stream. Future data written to /// this encoder will be the compressed into the stream `w` provided. /// /// # Errors /// /// This function will perform I/O to complete this stream, and any I/O /// errors which occur will be returned from this function. pub fn reset(&mut self, w: W) -> io::Result { self.inner.finish()?; self.inner.data.reset(); Ok(self.inner.replace(w)) } /// Attempt to finish this output stream, writing out final chunks of data. /// /// Note that this function can only be used once data has finished being /// written to the output stream. After this function is called then further /// calls to `write` may result in a panic. /// /// # Panics /// /// Attempts to write data to this stream may result in a panic after this /// function is called. /// /// # Errors /// /// This function will perform I/O to complete this stream, and any I/O /// errors which occur will be returned from this function. pub fn try_finish(&mut self) -> io::Result<()> { self.inner.finish() } /// Consumes this encoder, flushing the output stream. /// /// This will flush the underlying data stream, close off the compressed /// stream and, if successful, return the contained writer. /// /// Note that this function may not be suitable to call in a situation where /// the underlying stream is an asynchronous I/O stream. To finish a stream /// the `try_finish` (or `shutdown`) method should be used instead. To /// re-acquire ownership of a stream it is safe to call this method after /// `try_finish` or `shutdown` has returned `Ok`. /// /// # Errors /// /// This function will perform I/O to complete this stream, and any I/O /// errors which occur will be returned from this function. pub fn finish(mut self) -> io::Result { self.inner.finish()?; Ok(self.inner.take_inner()) } /// Consumes this encoder, flushing the output stream. /// /// This will flush the underlying data stream and then return the contained /// writer if the flush succeeded. /// The compressed stream will not closed but only flushed. This /// means that obtained byte array can by extended by another deflated /// stream. To close the stream add the two bytes 0x3 and 0x0. /// /// # Errors /// /// This function will perform I/O to complete this stream, and any I/O /// errors which occur will be returned from this function. pub fn flush_finish(mut self) -> io::Result { self.inner.flush()?; Ok(self.inner.take_inner()) } /// Returns the number of bytes that have been written to this compresor. /// /// Note that not all bytes written to this object may be accounted for, /// there may still be some active buffering. pub fn total_in(&self) -> u64 { self.inner.data.total_in() } /// Returns the number of bytes that the compressor has produced. /// /// Note that not all bytes may have been written yet, some may still be /// buffered. pub fn total_out(&self) -> u64 { self.inner.data.total_out() } } impl Write for DeflateEncoder { fn write(&mut self, buf: &[u8]) -> io::Result { self.inner.write(buf) } fn flush(&mut self) -> io::Result<()> { self.inner.flush() } } #[cfg(feature = "tokio")] impl AsyncWrite for DeflateEncoder { fn shutdown(&mut self) -> Poll<(), io::Error> { self.inner.finish()?; self.inner.get_mut().shutdown() } } impl Read for DeflateEncoder { fn read(&mut self, buf: &mut [u8]) -> io::Result { self.inner.get_mut().read(buf) } } #[cfg(feature = "tokio")] impl AsyncRead for DeflateEncoder {} /// A DEFLATE decoder, or decompressor. /// /// This structure implements a [`Write`] and will emit a stream of decompressed /// data when fed a stream of compressed data. /// /// [`Write`]: https://doc.rust-lang.org/std/io/trait.Read.html /// /// # Examples /// /// ``` /// use std::io::prelude::*; /// use std::io; /// # use flate2::Compression; /// # use flate2::write::DeflateEncoder; /// use flate2::write::DeflateDecoder; /// /// # fn main() { /// # let mut e = DeflateEncoder::new(Vec::new(), Compression::default()); /// # e.write_all(b"Hello World").unwrap(); /// # let bytes = e.finish().unwrap(); /// # println!("{}", decode_writer(bytes).unwrap()); /// # } /// // Uncompresses a Deflate Encoded vector of bytes and returns a string or error /// // Here Vec implements Write /// fn decode_writer(bytes: Vec) -> io::Result { /// let mut writer = Vec::new(); /// let mut deflater = DeflateDecoder::new(writer); /// deflater.write_all(&bytes[..])?; /// writer = deflater.finish()?; /// let return_string = String::from_utf8(writer).expect("String parsing error"); /// Ok(return_string) /// } /// ``` #[derive(Debug)] pub struct DeflateDecoder { inner: zio::Writer, } impl DeflateDecoder { /// Creates a new decoder which will write uncompressed data to the stream. /// /// When this encoder is dropped or unwrapped the final pieces of data will /// be flushed. pub fn new(w: W) -> DeflateDecoder { DeflateDecoder { inner: zio::Writer::new(w, Decompress::new(false)), } } /// Acquires a reference to the underlying writer. pub fn get_ref(&self) -> &W { self.inner.get_ref() } /// Acquires a mutable reference to the underlying writer. /// /// Note that mutating the output/input state of the stream may corrupt this /// object, so care must be taken when using this method. pub fn get_mut(&mut self) -> &mut W { self.inner.get_mut() } /// Resets the state of this decoder entirely, swapping out the output /// stream for another. /// /// This function will finish encoding the current stream into the current /// output stream before swapping out the two output streams. /// /// This will then reset the internal state of this decoder and replace the /// output stream with the one provided, returning the previous output /// stream. Future data written to this decoder will be decompressed into /// the output stream `w`. /// /// # Errors /// /// This function will perform I/O to finish the stream, and if that I/O /// returns an error then that will be returned from this function. pub fn reset(&mut self, w: W) -> io::Result { self.inner.finish()?; self.inner.data = Decompress::new(false); Ok(self.inner.replace(w)) } /// Attempt to finish this output stream, writing out final chunks of data. /// /// Note that this function can only be used once data has finished being /// written to the output stream. After this function is called then further /// calls to `write` may result in a panic. /// /// # Panics /// /// Attempts to write data to this stream may result in a panic after this /// function is called. /// /// # Errors /// /// This function will perform I/O to finish the stream, returning any /// errors which happen. pub fn try_finish(&mut self) -> io::Result<()> { self.inner.finish() } /// Consumes this encoder, flushing the output stream. /// /// This will flush the underlying data stream and then return the contained /// writer if the flush succeeded. /// /// Note that this function may not be suitable to call in a situation where /// the underlying stream is an asynchronous I/O stream. To finish a stream /// the `try_finish` (or `shutdown`) method should be used instead. To /// re-acquire ownership of a stream it is safe to call this method after /// `try_finish` or `shutdown` has returned `Ok`. /// /// # Errors /// /// This function will perform I/O to complete this stream, and any I/O /// errors which occur will be returned from this function. pub fn finish(mut self) -> io::Result { self.inner.finish()?; Ok(self.inner.take_inner()) } /// Returns the number of bytes that the decompressor has consumed for /// decompression. /// /// Note that this will likely be smaller than the number of bytes /// successfully written to this stream due to internal buffering. pub fn total_in(&self) -> u64 { self.inner.data.total_in() } /// Returns the number of bytes that the decompressor has written to its /// output stream. pub fn total_out(&self) -> u64 { self.inner.data.total_out() } } impl Write for DeflateDecoder { fn write(&mut self, buf: &[u8]) -> io::Result { self.inner.write(buf) } fn flush(&mut self) -> io::Result<()> { self.inner.flush() } } #[cfg(feature = "tokio")] impl AsyncWrite for DeflateDecoder { fn shutdown(&mut self) -> Poll<(), io::Error> { self.inner.finish()?; self.inner.get_mut().shutdown() } } impl Read for DeflateDecoder { fn read(&mut self, buf: &mut [u8]) -> io::Result { self.inner.get_mut().read(buf) } } #[cfg(feature = "tokio")] impl AsyncRead for DeflateDecoder {} flate2-1.0.22/src/ffi/c.rs000064400000000000000000000316410072674642500132430ustar 00000000000000//! Implementation for C backends. use std::alloc::{self, Layout}; use std::cmp; use std::convert::TryFrom; use std::fmt; use std::marker; use std::ops::{Deref, DerefMut}; use std::ptr; pub use libc::{c_int, c_uint, c_void, size_t}; use super::*; use crate::mem::{self, FlushDecompress, Status}; // miniz doesn't provide any error messages, so only enable the field when we use a real zlib #[derive(Default)] pub struct ErrorMessage(#[cfg(feature = "any_zlib")] Option<&'static str>); impl ErrorMessage { pub fn get(&self) -> Option<&str> { #[cfg(feature = "any_zlib")] { self.0 } #[cfg(not(feature = "any_zlib"))] { None } } } pub struct StreamWrapper { pub inner: Box, } impl fmt::Debug for StreamWrapper { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { write!(f, "StreamWrapper") } } impl Default for StreamWrapper { fn default() -> StreamWrapper { StreamWrapper { inner: Box::new(mz_stream { next_in: ptr::null_mut(), avail_in: 0, total_in: 0, next_out: ptr::null_mut(), avail_out: 0, total_out: 0, msg: ptr::null_mut(), adler: 0, data_type: 0, reserved: 0, opaque: ptr::null_mut(), state: ptr::null_mut(), #[cfg(all(feature = "any_zlib", not(feature = "cloudflare-zlib-sys")))] zalloc, #[cfg(all(feature = "any_zlib", not(feature = "cloudflare-zlib-sys")))] zfree, #[cfg(not(all(feature = "any_zlib", not(feature = "cloudflare-zlib-sys"))))] zalloc: Some(zalloc), #[cfg(not(all(feature = "any_zlib", not(feature = "cloudflare-zlib-sys"))))] zfree: Some(zfree), }), } } } const ALIGN: usize = std::mem::align_of::(); fn align_up(size: usize, align: usize) -> usize { (size + align - 1) & !(align - 1) } extern "C" fn zalloc(_ptr: *mut c_void, items: AllocSize, item_size: AllocSize) -> *mut c_void { // We need to multiply `items` and `item_size` to get the actual desired // allocation size. Since `zfree` doesn't receive a size argument we // also need to allocate space for a `usize` as a header so we can store // how large the allocation is to deallocate later. let size = match items .checked_mul(item_size) .and_then(|i| usize::try_from(i).ok()) .map(|size| align_up(size, ALIGN)) .and_then(|i| i.checked_add(std::mem::size_of::())) { Some(i) => i, None => return ptr::null_mut(), }; // Make sure the `size` isn't too big to fail `Layout`'s restrictions let layout = match Layout::from_size_align(size, ALIGN) { Ok(layout) => layout, Err(_) => return ptr::null_mut(), }; unsafe { // Allocate the data, and if successful store the size we allocated // at the beginning and then return an offset pointer. let ptr = alloc::alloc(layout) as *mut usize; if ptr.is_null() { return ptr as *mut c_void; } *ptr = size; ptr.add(1) as *mut c_void } } extern "C" fn zfree(_ptr: *mut c_void, address: *mut c_void) { unsafe { // Move our address being free'd back one pointer, read the size we // stored in `zalloc`, and then free it using the standard Rust // allocator. let ptr = (address as *mut usize).offset(-1); let size = *ptr; let layout = Layout::from_size_align_unchecked(size, ALIGN); alloc::dealloc(ptr as *mut u8, layout) } } impl Deref for StreamWrapper { type Target = mz_stream; fn deref(&self) -> &Self::Target { &*self.inner } } impl DerefMut for StreamWrapper { fn deref_mut(&mut self) -> &mut Self::Target { &mut *self.inner } } unsafe impl Send for Stream {} unsafe impl Sync for Stream {} /// Trait used to call the right destroy/end function on the inner /// stream object on drop. pub trait Direction { unsafe fn destroy(stream: *mut mz_stream) -> c_int; } #[derive(Debug)] pub enum DirCompress {} #[derive(Debug)] pub enum DirDecompress {} #[derive(Debug)] pub struct Stream { pub stream_wrapper: StreamWrapper, pub total_in: u64, pub total_out: u64, pub _marker: marker::PhantomData, } impl Stream { pub fn msg(&self) -> ErrorMessage { #[cfg(feature = "any_zlib")] { let msg = self.stream_wrapper.msg; ErrorMessage(if msg.is_null() { None } else { let s = unsafe { std::ffi::CStr::from_ptr(msg) }; std::str::from_utf8(s.to_bytes()).ok() }) } #[cfg(not(feature = "any_zlib"))] { ErrorMessage() } } } impl Drop for Stream { fn drop(&mut self) { unsafe { let _ = D::destroy(&mut *self.stream_wrapper); } } } impl Direction for DirCompress { unsafe fn destroy(stream: *mut mz_stream) -> c_int { mz_deflateEnd(stream) } } impl Direction for DirDecompress { unsafe fn destroy(stream: *mut mz_stream) -> c_int { mz_inflateEnd(stream) } } #[derive(Debug)] pub struct Inflate { pub inner: Stream, } impl InflateBackend for Inflate { fn make(zlib_header: bool, window_bits: u8) -> Self { unsafe { let mut state = StreamWrapper::default(); let ret = mz_inflateInit2( &mut *state, if zlib_header { window_bits as c_int } else { -(window_bits as c_int) }, ); assert_eq!(ret, 0); Inflate { inner: Stream { stream_wrapper: state, total_in: 0, total_out: 0, _marker: marker::PhantomData, }, } } } fn decompress( &mut self, input: &[u8], output: &mut [u8], flush: FlushDecompress, ) -> Result { let raw = &mut *self.inner.stream_wrapper; raw.msg = ptr::null_mut(); raw.next_in = input.as_ptr() as *mut u8; raw.avail_in = cmp::min(input.len(), c_uint::max_value() as usize) as c_uint; raw.next_out = output.as_mut_ptr(); raw.avail_out = cmp::min(output.len(), c_uint::max_value() as usize) as c_uint; let rc = unsafe { mz_inflate(raw, flush as c_int) }; // Unfortunately the total counters provided by zlib might be only // 32 bits wide and overflow while processing large amounts of data. self.inner.total_in += (raw.next_in as usize - input.as_ptr() as usize) as u64; self.inner.total_out += (raw.next_out as usize - output.as_ptr() as usize) as u64; match rc { MZ_DATA_ERROR | MZ_STREAM_ERROR => mem::decompress_failed(self.inner.msg()), MZ_OK => Ok(Status::Ok), MZ_BUF_ERROR => Ok(Status::BufError), MZ_STREAM_END => Ok(Status::StreamEnd), MZ_NEED_DICT => mem::decompress_need_dict(raw.adler as u32), c => panic!("unknown return code: {}", c), } } #[cfg(feature = "any_zlib")] fn reset(&mut self, zlib_header: bool) { let bits = if zlib_header { MZ_DEFAULT_WINDOW_BITS } else { -MZ_DEFAULT_WINDOW_BITS }; unsafe { inflateReset2(&mut *self.inner.stream_wrapper, bits); } self.inner.total_out = 0; self.inner.total_in = 0; } #[cfg(not(feature = "any_zlib"))] fn reset(&mut self, zlib_header: bool) { *self = Self::make(zlib_header, MZ_DEFAULT_WINDOW_BITS as u8); } } impl Backend for Inflate { #[inline] fn total_in(&self) -> u64 { self.inner.total_in } #[inline] fn total_out(&self) -> u64 { self.inner.total_out } } #[derive(Debug)] pub struct Deflate { pub inner: Stream, } impl DeflateBackend for Deflate { fn make(level: Compression, zlib_header: bool, window_bits: u8) -> Self { unsafe { let mut state = StreamWrapper::default(); let ret = mz_deflateInit2( &mut *state, level.0 as c_int, MZ_DEFLATED, if zlib_header { window_bits as c_int } else { -(window_bits as c_int) }, 8, MZ_DEFAULT_STRATEGY, ); assert_eq!(ret, 0); Deflate { inner: Stream { stream_wrapper: state, total_in: 0, total_out: 0, _marker: marker::PhantomData, }, } } } fn compress( &mut self, input: &[u8], output: &mut [u8], flush: FlushCompress, ) -> Result { let raw = &mut *self.inner.stream_wrapper; raw.msg = ptr::null_mut(); raw.next_in = input.as_ptr() as *mut _; raw.avail_in = cmp::min(input.len(), c_uint::max_value() as usize) as c_uint; raw.next_out = output.as_mut_ptr(); raw.avail_out = cmp::min(output.len(), c_uint::max_value() as usize) as c_uint; let rc = unsafe { mz_deflate(raw, flush as c_int) }; // Unfortunately the total counters provided by zlib might be only // 32 bits wide and overflow while processing large amounts of data. self.inner.total_in += (raw.next_in as usize - input.as_ptr() as usize) as u64; self.inner.total_out += (raw.next_out as usize - output.as_ptr() as usize) as u64; match rc { MZ_OK => Ok(Status::Ok), MZ_BUF_ERROR => Ok(Status::BufError), MZ_STREAM_END => Ok(Status::StreamEnd), MZ_STREAM_ERROR => mem::compress_failed(self.inner.msg()), c => panic!("unknown return code: {}", c), } } fn reset(&mut self) { self.inner.total_in = 0; self.inner.total_out = 0; let rc = unsafe { mz_deflateReset(&mut *self.inner.stream_wrapper) }; assert_eq!(rc, MZ_OK); } } impl Backend for Deflate { #[inline] fn total_in(&self) -> u64 { self.inner.total_in } #[inline] fn total_out(&self) -> u64 { self.inner.total_out } } pub use self::c_backend::*; /// Miniz specific #[cfg(not(feature = "any_zlib"))] mod c_backend { pub use miniz_sys::*; pub type AllocSize = libc::size_t; } /// Zlib specific - make zlib mimic miniz' API #[cfg(feature = "any_zlib")] #[allow(bad_style)] mod c_backend { use libc::{c_char, c_int}; use std::mem; #[cfg(feature = "cloudflare_zlib")] use cloudflare_zlib_sys as libz; #[cfg(not(feature = "cloudflare_zlib"))] use libz_sys as libz; pub use libz::deflate as mz_deflate; pub use libz::deflateEnd as mz_deflateEnd; pub use libz::deflateReset as mz_deflateReset; pub use libz::inflate as mz_inflate; pub use libz::inflateEnd as mz_inflateEnd; pub use libz::z_stream as mz_stream; pub use libz::*; pub use libz::Z_BLOCK as MZ_BLOCK; pub use libz::Z_BUF_ERROR as MZ_BUF_ERROR; pub use libz::Z_DATA_ERROR as MZ_DATA_ERROR; pub use libz::Z_DEFAULT_STRATEGY as MZ_DEFAULT_STRATEGY; pub use libz::Z_DEFLATED as MZ_DEFLATED; pub use libz::Z_FINISH as MZ_FINISH; pub use libz::Z_FULL_FLUSH as MZ_FULL_FLUSH; pub use libz::Z_NEED_DICT as MZ_NEED_DICT; pub use libz::Z_NO_FLUSH as MZ_NO_FLUSH; pub use libz::Z_OK as MZ_OK; pub use libz::Z_PARTIAL_FLUSH as MZ_PARTIAL_FLUSH; pub use libz::Z_STREAM_END as MZ_STREAM_END; pub use libz::Z_STREAM_ERROR as MZ_STREAM_ERROR; pub use libz::Z_SYNC_FLUSH as MZ_SYNC_FLUSH; pub type AllocSize = libz::uInt; pub const MZ_DEFAULT_WINDOW_BITS: c_int = 15; const ZLIB_VERSION: &'static str = "1.2.8\0"; pub unsafe extern "C" fn mz_deflateInit2( stream: *mut mz_stream, level: c_int, method: c_int, window_bits: c_int, mem_level: c_int, strategy: c_int, ) -> c_int { libz::deflateInit2_( stream, level, method, window_bits, mem_level, strategy, ZLIB_VERSION.as_ptr() as *const c_char, mem::size_of::() as c_int, ) } pub unsafe extern "C" fn mz_inflateInit2(stream: *mut mz_stream, window_bits: c_int) -> c_int { libz::inflateInit2_( stream, window_bits, ZLIB_VERSION.as_ptr() as *const c_char, mem::size_of::() as c_int, ) } } flate2-1.0.22/src/ffi/mod.rs000064400000000000000000000026330072674642500135770ustar 00000000000000//! This module contains backend-specific code. use crate::mem::{CompressError, DecompressError, FlushCompress, FlushDecompress, Status}; use crate::Compression; /// Traits specifying the interface of the backends. /// /// Sync + Send are added as a condition to ensure they are available /// for the frontend. pub trait Backend: Sync + Send { fn total_in(&self) -> u64; fn total_out(&self) -> u64; } pub trait InflateBackend: Backend { fn make(zlib_header: bool, window_bits: u8) -> Self; fn decompress( &mut self, input: &[u8], output: &mut [u8], flush: FlushDecompress, ) -> Result; fn reset(&mut self, zlib_header: bool); } pub trait DeflateBackend: Backend { fn make(level: Compression, zlib_header: bool, window_bits: u8) -> Self; fn compress( &mut self, input: &[u8], output: &mut [u8], flush: FlushCompress, ) -> Result; fn reset(&mut self); } // Default to Rust implementation unless explicitly opted in to a different backend. cfg_if::cfg_if! { if #[cfg(any(feature = "miniz-sys", feature = "any_zlib"))] { mod c; pub use self::c::*; } else { mod rust; pub use self::rust::*; } } impl std::fmt::Debug for ErrorMessage { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { self.get().fmt(f) } } flate2-1.0.22/src/ffi/rust.rs000064400000000000000000000113600072674642500140120ustar 00000000000000//! Implementation for miniz_oxide rust backend. use std::convert::TryInto; use std::fmt; use miniz_oxide::deflate::core::CompressorOxide; use miniz_oxide::inflate::stream::InflateState; pub use miniz_oxide::*; pub const MZ_NO_FLUSH: isize = MZFlush::None as isize; pub const MZ_PARTIAL_FLUSH: isize = MZFlush::Partial as isize; pub const MZ_SYNC_FLUSH: isize = MZFlush::Sync as isize; pub const MZ_FULL_FLUSH: isize = MZFlush::Full as isize; pub const MZ_FINISH: isize = MZFlush::Finish as isize; use super::*; use crate::mem; // miniz_oxide doesn't provide any error messages (yet?) #[derive(Default)] pub struct ErrorMessage; impl ErrorMessage { pub fn get(&self) -> Option<&str> { None } } fn format_from_bool(zlib_header: bool) -> DataFormat { if zlib_header { DataFormat::Zlib } else { DataFormat::Raw } } pub struct Inflate { inner: Box, total_in: u64, total_out: u64, } impl fmt::Debug for Inflate { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { write!( f, "miniz_oxide inflate internal state. total_in: {}, total_out: {}", self.total_in, self.total_out, ) } } impl InflateBackend for Inflate { fn make(zlib_header: bool, _window_bits: u8) -> Self { let format = format_from_bool(zlib_header); Inflate { inner: InflateState::new_boxed(format), total_in: 0, total_out: 0, } } fn decompress( &mut self, input: &[u8], output: &mut [u8], flush: FlushDecompress, ) -> Result { let flush = MZFlush::new(flush as i32).unwrap(); let res = inflate::stream::inflate(&mut self.inner, input, output, flush); self.total_in += res.bytes_consumed as u64; self.total_out += res.bytes_written as u64; match res.status { Ok(status) => match status { MZStatus::Ok => Ok(Status::Ok), MZStatus::StreamEnd => Ok(Status::StreamEnd), MZStatus::NeedDict => { mem::decompress_need_dict(self.inner.decompressor().adler32().unwrap_or(0)) } }, Err(status) => match status { MZError::Buf => Ok(Status::BufError), _ => mem::decompress_failed(ErrorMessage), }, } } fn reset(&mut self, zlib_header: bool) { self.inner.reset(format_from_bool(zlib_header)); self.total_in = 0; self.total_out = 0; } } impl Backend for Inflate { #[inline] fn total_in(&self) -> u64 { self.total_in } #[inline] fn total_out(&self) -> u64 { self.total_out } } pub struct Deflate { inner: Box, total_in: u64, total_out: u64, } impl fmt::Debug for Deflate { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { write!( f, "miniz_oxide deflate internal state. total_in: {}, total_out: {}", self.total_in, self.total_out, ) } } impl DeflateBackend for Deflate { fn make(level: Compression, zlib_header: bool, _window_bits: u8) -> Self { // Check in case the integer value changes at some point. debug_assert!(level.level() <= 10); let mut inner: Box = Box::default(); let format = format_from_bool(zlib_header); inner.set_format_and_level(format, level.level().try_into().unwrap_or(1)); Deflate { inner, total_in: 0, total_out: 0, } } fn compress( &mut self, input: &[u8], output: &mut [u8], flush: FlushCompress, ) -> Result { let flush = MZFlush::new(flush as i32).unwrap(); let res = deflate::stream::deflate(&mut self.inner, input, output, flush); self.total_in += res.bytes_consumed as u64; self.total_out += res.bytes_written as u64; match res.status { Ok(status) => match status { MZStatus::Ok => Ok(Status::Ok), MZStatus::StreamEnd => Ok(Status::StreamEnd), MZStatus::NeedDict => mem::compress_failed(ErrorMessage), }, Err(status) => match status { MZError::Buf => Ok(Status::BufError), _ => mem::compress_failed(ErrorMessage), }, } } fn reset(&mut self) { self.total_in = 0; self.total_out = 0; self.inner.reset(); } } impl Backend for Deflate { #[inline] fn total_in(&self) -> u64 { self.total_in } #[inline] fn total_out(&self) -> u64 { self.total_out } } flate2-1.0.22/src/gz/bufread.rs000064400000000000000000000657310072674642500143140ustar 00000000000000use std::cmp; use std::io; use std::io::prelude::*; use std::mem; #[cfg(feature = "tokio")] use futures::Poll; #[cfg(feature = "tokio")] use tokio_io::{AsyncRead, AsyncWrite}; use super::{GzBuilder, GzHeader}; use super::{FCOMMENT, FEXTRA, FHCRC, FNAME}; use crate::crc::{Crc, CrcReader}; use crate::deflate; use crate::Compression; fn copy(into: &mut [u8], from: &[u8], pos: &mut usize) -> usize { let min = cmp::min(into.len(), from.len() - *pos); for (slot, val) in into.iter_mut().zip(from[*pos..*pos + min].iter()) { *slot = *val; } *pos += min; return min; } pub(crate) fn corrupt() -> io::Error { io::Error::new( io::ErrorKind::InvalidInput, "corrupt gzip stream does not have a matching checksum", ) } fn bad_header() -> io::Error { io::Error::new(io::ErrorKind::InvalidInput, "invalid gzip header") } fn read_le_u16(r: &mut Buffer) -> io::Result { let mut b = [0; 2]; r.read_and_forget(&mut b)?; Ok((b[0] as u16) | ((b[1] as u16) << 8)) } fn read_gz_header_part<'a, R: Read>(r: &'a mut Buffer<'a, R>) -> io::Result<()> { loop { match r.part.state { GzHeaderParsingState::Start => { let mut header = [0; 10]; r.read_and_forget(&mut header)?; if header[0] != 0x1f || header[1] != 0x8b { return Err(bad_header()); } if header[2] != 8 { return Err(bad_header()); } r.part.flg = header[3]; r.part.header.mtime = ((header[4] as u32) << 0) | ((header[5] as u32) << 8) | ((header[6] as u32) << 16) | ((header[7] as u32) << 24); let _xfl = header[8]; r.part.header.operating_system = header[9]; r.part.state = GzHeaderParsingState::Xlen; } GzHeaderParsingState::Xlen => { if r.part.flg & FEXTRA != 0 { r.part.xlen = read_le_u16(r)?; } r.part.state = GzHeaderParsingState::Extra; } GzHeaderParsingState::Extra => { if r.part.flg & FEXTRA != 0 { let mut extra = vec![0; r.part.xlen as usize]; r.read_and_forget(&mut extra)?; r.part.header.extra = Some(extra); } r.part.state = GzHeaderParsingState::Filename; } GzHeaderParsingState::Filename => { if r.part.flg & FNAME != 0 { if None == r.part.header.filename { r.part.header.filename = Some(Vec::new()); }; for byte in r.bytes() { let byte = byte?; if byte == 0 { break; } } } r.part.state = GzHeaderParsingState::Comment; } GzHeaderParsingState::Comment => { if r.part.flg & FCOMMENT != 0 { if None == r.part.header.comment { r.part.header.comment = Some(Vec::new()); }; for byte in r.bytes() { let byte = byte?; if byte == 0 { break; } } } r.part.state = GzHeaderParsingState::Crc; } GzHeaderParsingState::Crc => { if r.part.flg & FHCRC != 0 { let stored_crc = read_le_u16(r)?; let calced_crc = r.part.crc.sum() as u16; if stored_crc != calced_crc { return Err(corrupt()); } } return Ok(()); } } } } pub(crate) fn read_gz_header(r: &mut R) -> io::Result { let mut part = GzHeaderPartial::new(); let result = { let mut reader = Buffer::new(&mut part, r); read_gz_header_part(&mut reader) }; match result { Ok(()) => { return Ok(part.take_header()); } Err(err) => { return Err(err); } }; } /// A gzip streaming encoder /// /// This structure exposes a [`BufRead`] interface that will read uncompressed data /// from the underlying reader and expose the compressed version as a [`BufRead`] /// interface. /// /// [`BufRead`]: https://doc.rust-lang.org/std/io/trait.BufRead.html /// /// # Examples /// /// ``` /// use std::io::prelude::*; /// use std::io; /// use flate2::Compression; /// use flate2::bufread::GzEncoder; /// use std::fs::File; /// use std::io::BufReader; /// /// // Opens sample file, compresses the contents and returns a Vector or error /// // File wrapped in a BufReader implements BufRead /// /// fn open_hello_world() -> io::Result> { /// let f = File::open("examples/hello_world.txt")?; /// let b = BufReader::new(f); /// let mut gz = GzEncoder::new(b, Compression::fast()); /// let mut buffer = Vec::new(); /// gz.read_to_end(&mut buffer)?; /// Ok(buffer) /// } /// ``` #[derive(Debug)] pub struct GzEncoder { inner: deflate::bufread::DeflateEncoder>, header: Vec, pos: usize, eof: bool, } pub fn gz_encoder(header: Vec, r: R, lvl: Compression) -> GzEncoder { let crc = CrcReader::new(r); GzEncoder { inner: deflate::bufread::DeflateEncoder::new(crc, lvl), header: header, pos: 0, eof: false, } } impl GzEncoder { /// Creates a new encoder which will use the given compression level. /// /// The encoder is not configured specially for the emitted header. For /// header configuration, see the `GzBuilder` type. /// /// The data read from the stream `r` will be compressed and available /// through the returned reader. pub fn new(r: R, level: Compression) -> GzEncoder { GzBuilder::new().buf_read(r, level) } fn read_footer(&mut self, into: &mut [u8]) -> io::Result { if self.pos == 8 { return Ok(0); } let crc = self.inner.get_ref().crc(); let ref arr = [ (crc.sum() >> 0) as u8, (crc.sum() >> 8) as u8, (crc.sum() >> 16) as u8, (crc.sum() >> 24) as u8, (crc.amount() >> 0) as u8, (crc.amount() >> 8) as u8, (crc.amount() >> 16) as u8, (crc.amount() >> 24) as u8, ]; Ok(copy(into, arr, &mut self.pos)) } } impl GzEncoder { /// Acquires a reference to the underlying reader. pub fn get_ref(&self) -> &R { self.inner.get_ref().get_ref() } /// Acquires a mutable reference to the underlying reader. /// /// Note that mutation of the reader may result in surprising results if /// this encoder is continued to be used. pub fn get_mut(&mut self) -> &mut R { self.inner.get_mut().get_mut() } /// Returns the underlying stream, consuming this encoder pub fn into_inner(self) -> R { self.inner.into_inner().into_inner() } } #[inline] fn finish(buf: &[u8; 8]) -> (u32, u32) { let crc = ((buf[0] as u32) << 0) | ((buf[1] as u32) << 8) | ((buf[2] as u32) << 16) | ((buf[3] as u32) << 24); let amt = ((buf[4] as u32) << 0) | ((buf[5] as u32) << 8) | ((buf[6] as u32) << 16) | ((buf[7] as u32) << 24); (crc, amt) } impl Read for GzEncoder { fn read(&mut self, mut into: &mut [u8]) -> io::Result { let mut amt = 0; if self.eof { return self.read_footer(into); } else if self.pos < self.header.len() { amt += copy(into, &self.header, &mut self.pos); if amt == into.len() { return Ok(amt); } let tmp = into; into = &mut tmp[amt..]; } match self.inner.read(into)? { 0 => { self.eof = true; self.pos = 0; self.read_footer(into) } n => Ok(amt + n), } } } impl Write for GzEncoder { fn write(&mut self, buf: &[u8]) -> io::Result { self.get_mut().write(buf) } fn flush(&mut self) -> io::Result<()> { self.get_mut().flush() } } /// A gzip streaming decoder /// /// This structure consumes a [`BufRead`] interface, reading compressed data /// from the underlying reader, and emitting uncompressed data. /// /// [`BufRead`]: https://doc.rust-lang.org/std/io/trait.BufRead.html /// /// # Examples /// /// ``` /// use std::io::prelude::*; /// use std::io; /// # use flate2::Compression; /// # use flate2::write::GzEncoder; /// use flate2::bufread::GzDecoder; /// /// # fn main() { /// # let mut e = GzEncoder::new(Vec::new(), Compression::default()); /// # e.write_all(b"Hello World").unwrap(); /// # let bytes = e.finish().unwrap(); /// # println!("{}", decode_reader(bytes).unwrap()); /// # } /// # /// // Uncompresses a Gz Encoded vector of bytes and returns a string or error /// // Here &[u8] implements BufRead /// /// fn decode_reader(bytes: Vec) -> io::Result { /// let mut gz = GzDecoder::new(&bytes[..]); /// let mut s = String::new(); /// gz.read_to_string(&mut s)?; /// Ok(s) /// } /// ``` #[derive(Debug)] pub struct GzDecoder { inner: GzState, header: Option, reader: CrcReader>, multi: bool, } #[derive(Debug)] pub enum GzHeaderParsingState { Start, Xlen, Extra, Filename, Comment, Crc, } #[derive(Debug)] pub struct GzHeaderPartial { buf: Vec, state: GzHeaderParsingState, flg: u8, xlen: u16, crc: Crc, header: GzHeader, } impl GzHeaderPartial { fn new() -> GzHeaderPartial { GzHeaderPartial { buf: Vec::with_capacity(10), // minimum header length state: GzHeaderParsingState::Start, flg: 0, xlen: 0, crc: Crc::new(), header: GzHeader { extra: None, filename: None, comment: None, operating_system: 0, mtime: 0, }, } } pub fn take_header(self) -> GzHeader { return self.header; } } #[derive(Debug)] enum GzState { Header(GzHeaderPartial), Body, Finished(usize, [u8; 8]), Err(io::Error), End, } /// A small adapter which reads data originally from `buf` and then reads all /// further data from `reader`. This will also buffer all data read from /// `reader` into `buf` for reuse on a further call. struct Buffer<'a, T: 'a> { part: &'a mut GzHeaderPartial, buf_cur: usize, buf_max: usize, reader: &'a mut T, } impl<'a, T> Buffer<'a, T> { fn new(part: &'a mut GzHeaderPartial, reader: &'a mut T) -> Buffer<'a, T> { Buffer { reader, buf_cur: 0, buf_max: part.buf.len(), part, } } } impl<'a, T: Read> Read for Buffer<'a, T> { fn read(&mut self, buf: &mut [u8]) -> io::Result { let mut bufref = match self.part.state { GzHeaderParsingState::Filename => self.part.header.filename.as_mut(), GzHeaderParsingState::Comment => self.part.header.comment.as_mut(), _ => None, }; if let Some(ref mut b) = bufref { // we have a direct reference to a buffer where to write let len = self.reader.read(buf)?; if len > 0 && buf[len - 1] == 0 { // we do not append the final 0 b.extend_from_slice(&buf[..len - 1]); } else { b.extend_from_slice(&buf[..len]); } self.part.crc.update(&buf[..len]); Ok(len) } else if self.buf_cur == self.buf_max { // we read new bytes and also save them in self.part.buf let len = self.reader.read(buf)?; self.part.buf.extend_from_slice(&buf[..len]); self.part.crc.update(&buf[..len]); Ok(len) } else { // we first read the previously saved bytes let len = (&self.part.buf[self.buf_cur..self.buf_max]).read(buf)?; self.buf_cur += len; Ok(len) } } } impl<'a, T> Buffer<'a, T> where T: std::io::Read, { // If we manage to read all the bytes, we reset the buffer fn read_and_forget(&mut self, buf: &mut [u8]) -> io::Result { self.read_exact(buf)?; // we managed to read the whole buf // we will no longer need the previously saved bytes in self.part.buf let rlen = buf.len(); self.part.buf.truncate(0); self.buf_cur = 0; self.buf_max = 0; return Ok(rlen); } } impl GzDecoder { /// Creates a new decoder from the given reader, immediately parsing the /// gzip header. pub fn new(mut r: R) -> GzDecoder { let mut part = GzHeaderPartial::new(); let mut header = None; let result = { let mut reader = Buffer::new(&mut part, &mut r); read_gz_header_part(&mut reader) }; let state = match result { Ok(()) => { header = Some(part.take_header()); GzState::Body } Err(ref err) if io::ErrorKind::WouldBlock == err.kind() => GzState::Header(part), Err(err) => GzState::Err(err), }; GzDecoder { inner: state, reader: CrcReader::new(deflate::bufread::DeflateDecoder::new(r)), multi: false, header, } } fn multi(mut self, flag: bool) -> GzDecoder { self.multi = flag; self } } impl GzDecoder { /// Returns the header associated with this stream, if it was valid pub fn header(&self) -> Option<&GzHeader> { self.header.as_ref() } /// Acquires a reference to the underlying reader. pub fn get_ref(&self) -> &R { self.reader.get_ref().get_ref() } /// Acquires a mutable reference to the underlying stream. /// /// Note that mutation of the stream may result in surprising results if /// this encoder is continued to be used. pub fn get_mut(&mut self) -> &mut R { self.reader.get_mut().get_mut() } /// Consumes this decoder, returning the underlying reader. pub fn into_inner(self) -> R { self.reader.into_inner().into_inner() } } impl Read for GzDecoder { fn read(&mut self, into: &mut [u8]) -> io::Result { let GzDecoder { inner, header, reader, multi, } = self; loop { *inner = match mem::replace(inner, GzState::End) { GzState::Header(mut part) => { let result = { let mut reader = Buffer::new(&mut part, reader.get_mut().get_mut()); read_gz_header_part(&mut reader) }; let state = match result { Ok(()) => { *header = Some(part.take_header()); GzState::Body } Err(err) if io::ErrorKind::WouldBlock == err.kind() => { *inner = GzState::Header(part); return Err(err); } Err(err) => return Err(err), }; state } GzState::Body => { if into.is_empty() { *inner = GzState::Body; return Ok(0); } let n = reader.read(into).map_err(|err| { if io::ErrorKind::WouldBlock == err.kind() { *inner = GzState::Body; } err })?; match n { 0 => GzState::Finished(0, [0; 8]), n => { *inner = GzState::Body; return Ok(n); } } } GzState::Finished(pos, mut buf) => { if pos < buf.len() { let n = reader .get_mut() .get_mut() .read(&mut buf[pos..]) .and_then(|n| { if n == 0 { Err(io::ErrorKind::UnexpectedEof.into()) } else { Ok(n) } }) .map_err(|err| { if io::ErrorKind::WouldBlock == err.kind() { *inner = GzState::Finished(pos, buf); } err })?; GzState::Finished(pos + n, buf) } else { let (crc, amt) = finish(&buf); if crc != reader.crc().sum() || amt != reader.crc().amount() { return Err(corrupt()); } else if *multi { let is_eof = reader .get_mut() .get_mut() .fill_buf() .map(|buf| buf.is_empty()) .map_err(|err| { if io::ErrorKind::WouldBlock == err.kind() { *inner = GzState::Finished(pos, buf); } err })?; if is_eof { GzState::End } else { reader.reset(); reader.get_mut().reset_data(); header.take(); GzState::Header(GzHeaderPartial::new()) } } else { GzState::End } } } GzState::Err(err) => return Err(err), GzState::End => return Ok(0), }; } } } #[cfg(feature = "tokio")] impl AsyncRead for GzDecoder {} impl Write for GzDecoder { fn write(&mut self, buf: &[u8]) -> io::Result { self.get_mut().write(buf) } fn flush(&mut self) -> io::Result<()> { self.get_mut().flush() } } #[cfg(feature = "tokio")] impl AsyncWrite for GzDecoder { fn shutdown(&mut self) -> Poll<(), io::Error> { self.get_mut().shutdown() } } /// A gzip streaming decoder that decodes all members of a multistream /// /// 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 first gzip member. The multistream format is commonly used in /// bioinformatics, for example when using the BGZF compressed data. /// /// This structure exposes a [`BufRead`] interface that will consume all gzip members /// from the underlying reader and emit uncompressed data. /// /// [`BufRead`]: https://doc.rust-lang.org/std/io/trait.BufRead.html /// /// # Examples /// /// ``` /// use std::io::prelude::*; /// use std::io; /// # use flate2::Compression; /// # use flate2::write::GzEncoder; /// use flate2::bufread::MultiGzDecoder; /// /// # fn main() { /// # let mut e = GzEncoder::new(Vec::new(), Compression::default()); /// # e.write_all(b"Hello World").unwrap(); /// # let bytes = e.finish().unwrap(); /// # println!("{}", decode_reader(bytes).unwrap()); /// # } /// # /// // Uncompresses a Gz Encoded vector of bytes and returns a string or error /// // Here &[u8] implements BufRead /// /// fn decode_reader(bytes: Vec) -> io::Result { /// let mut gz = MultiGzDecoder::new(&bytes[..]); /// let mut s = String::new(); /// gz.read_to_string(&mut s)?; /// Ok(s) /// } /// ``` #[derive(Debug)] pub struct MultiGzDecoder(GzDecoder); impl MultiGzDecoder { /// Creates a new decoder from the given reader, immediately parsing the /// (first) gzip header. If the gzip stream contains multiple members all will /// be decoded. pub fn new(r: R) -> MultiGzDecoder { MultiGzDecoder(GzDecoder::new(r).multi(true)) } } impl MultiGzDecoder { /// Returns the current header associated with this stream, if it's valid pub fn header(&self) -> Option<&GzHeader> { self.0.header() } /// Acquires a reference to the underlying reader. pub fn get_ref(&self) -> &R { self.0.get_ref() } /// Acquires a mutable reference to the underlying stream. /// /// Note that mutation of the stream may result in surprising results if /// this encoder is continued to be used. pub fn get_mut(&mut self) -> &mut R { self.0.get_mut() } /// Consumes this decoder, returning the underlying reader. pub fn into_inner(self) -> R { self.0.into_inner() } } impl Read for MultiGzDecoder { fn read(&mut self, into: &mut [u8]) -> io::Result { self.0.read(into) } } #[cfg(feature = "tokio")] impl AsyncRead for MultiGzDecoder {} impl Write for MultiGzDecoder { fn write(&mut self, buf: &[u8]) -> io::Result { self.get_mut().write(buf) } fn flush(&mut self) -> io::Result<()> { self.get_mut().flush() } } #[cfg(feature = "tokio")] impl AsyncWrite for MultiGzDecoder { fn shutdown(&mut self) -> Poll<(), io::Error> { self.get_mut().shutdown() } } #[cfg(test)] pub mod tests { use crate::gz::bufread::*; use std::io; use std::io::{Cursor, Read, Write}; //a cursor turning EOF into blocking errors #[derive(Debug)] pub struct BlockingCursor { pub cursor: Cursor>, } impl BlockingCursor { pub fn new() -> BlockingCursor { BlockingCursor { cursor: Cursor::new(Vec::new()), } } pub fn set_position(&mut self, pos: u64) { return self.cursor.set_position(pos); } pub fn position(&mut self) -> u64 { return self.cursor.position(); } } impl Write for BlockingCursor { fn write(&mut self, buf: &[u8]) -> io::Result { return self.cursor.write(buf); } fn flush(&mut self) -> io::Result<()> { return self.cursor.flush(); } } impl Read for BlockingCursor { fn read(&mut self, buf: &mut [u8]) -> io::Result { //use the cursor, except it turns eof into blocking error let r = self.cursor.read(buf); match r { Err(ref err) => { if err.kind() == io::ErrorKind::UnexpectedEof { return Err(io::ErrorKind::WouldBlock.into()); } } Ok(0) => { //regular EOF turned into blocking error return Err(io::ErrorKind::WouldBlock.into()); } Ok(_n) => {} } return r; } } #[test] // test function read_and_forget of Buffer fn buffer_read_and_forget() { // this is unused except for the buffering let mut part = GzHeaderPartial::new(); // this is a reader which receives data afterwards let mut r = BlockingCursor::new(); let data = vec![1, 2, 3]; let mut out = Vec::with_capacity(7); match r.write_all(&data) { Ok(()) => {} _ => { panic!("Unexpected result for write_all"); } } r.set_position(0); // First read : successful for one byte let mut reader = Buffer::new(&mut part, &mut r); out.resize(1, 0); match reader.read_and_forget(&mut out) { Ok(1) => {} _ => { panic!("Unexpected result for read_and_forget with data"); } } // Second read : incomplete for 7 bytes (we have only 2) out.resize(7, 0); match reader.read_and_forget(&mut out) { Err(ref err) => { assert_eq!(io::ErrorKind::WouldBlock, err.kind()); } _ => { panic!("Unexpected result for read_and_forget with incomplete"); } } // 3 more data bytes have arrived let pos = r.position(); let data2 = vec![4, 5, 6]; match r.write_all(&data2) { Ok(()) => {} _ => { panic!("Unexpected result for write_all"); } } r.set_position(pos); // Third read : still incomplete for 7 bytes (we have 5) let mut reader2 = Buffer::new(&mut part, &mut r); match reader2.read_and_forget(&mut out) { Err(ref err) => { assert_eq!(io::ErrorKind::WouldBlock, err.kind()); } _ => { panic!("Unexpected result for read_and_forget with more incomplete"); } } // 3 more data bytes have arrived again let pos2 = r.position(); let data3 = vec![7, 8, 9]; match r.write_all(&data3) { Ok(()) => {} _ => { panic!("Unexpected result for write_all"); } } r.set_position(pos2); // Fourth read : now succesful for 7 bytes let mut reader3 = Buffer::new(&mut part, &mut r); match reader3.read_and_forget(&mut out) { Ok(7) => { assert_eq!(out[0], 2); assert_eq!(out[6], 8); } _ => { panic!("Unexpected result for read_and_forget with data"); } } // Fifth read : succesful for one more byte out.resize(1, 0); match reader3.read_and_forget(&mut out) { Ok(1) => { assert_eq!(out[0], 9); } _ => { panic!("Unexpected result for read_and_forget with data"); } } } } flate2-1.0.22/src/gz/mod.rs000064400000000000000000000300620072674642500134500ustar 00000000000000use std::ffi::CString; use std::io::prelude::*; use std::time; use crate::bufreader::BufReader; use crate::Compression; pub static FHCRC: u8 = 1 << 1; pub static FEXTRA: u8 = 1 << 2; pub static FNAME: u8 = 1 << 3; pub static FCOMMENT: u8 = 1 << 4; pub mod bufread; pub mod read; pub mod write; /// A structure representing the header of a gzip stream. /// /// The header can contain metadata about the file that was compressed, if /// present. #[derive(PartialEq, Clone, Debug, Default)] pub struct GzHeader { extra: Option>, filename: Option>, comment: Option>, operating_system: u8, mtime: u32, } impl GzHeader { /// Returns the `filename` field of this gzip stream's header, if present. pub fn filename(&self) -> Option<&[u8]> { self.filename.as_ref().map(|s| &s[..]) } /// Returns the `extra` field of this gzip stream's header, if present. pub fn extra(&self) -> Option<&[u8]> { self.extra.as_ref().map(|s| &s[..]) } /// Returns the `comment` field of this gzip stream's header, if present. pub fn comment(&self) -> Option<&[u8]> { self.comment.as_ref().map(|s| &s[..]) } /// Returns the `operating_system` field of this gzip stream's header. /// /// There are predefined values for various operating systems. /// 255 means that the value is unknown. pub fn operating_system(&self) -> u8 { self.operating_system } /// This gives the most recent modification time of the original file being compressed. /// /// The time is in Unix format, i.e., seconds since 00:00:00 GMT, Jan. 1, 1970. /// (Note that this may cause problems for MS-DOS and other systems that use local /// rather than Universal time.) If the compressed data did not come from a file, /// `mtime` is set to the time at which compression started. /// `mtime` = 0 means no time stamp is available. /// /// The usage of `mtime` is discouraged because of Year 2038 problem. pub fn mtime(&self) -> u32 { self.mtime } /// Returns the most recent modification time represented by a date-time type. /// Returns `None` if the value of the underlying counter is 0, /// indicating no time stamp is available. /// /// /// The time is measured as seconds since 00:00:00 GMT, Jan. 1 1970. /// See [`mtime`](#method.mtime) for more detail. pub fn mtime_as_datetime(&self) -> Option { if self.mtime == 0 { None } else { let duration = time::Duration::new(u64::from(self.mtime), 0); let datetime = time::UNIX_EPOCH + duration; Some(datetime) } } } /// A builder structure to create a new gzip Encoder. /// /// This structure controls header configuration options such as the filename. /// /// # Examples /// /// ``` /// use std::io::prelude::*; /// # use std::io; /// use std::fs::File; /// use flate2::GzBuilder; /// use flate2::Compression; /// /// // GzBuilder opens a file and writes a sample string using GzBuilder pattern /// /// # fn sample_builder() -> Result<(), io::Error> { /// let f = File::create("examples/hello_world.gz")?; /// let mut gz = GzBuilder::new() /// .filename("hello_world.txt") /// .comment("test file, please delete") /// .write(f, Compression::default()); /// gz.write_all(b"hello world")?; /// gz.finish()?; /// # Ok(()) /// # } /// ``` #[derive(Debug)] pub struct GzBuilder { extra: Option>, filename: Option, comment: Option, operating_system: Option, mtime: u32, } impl GzBuilder { /// Create a new blank builder with no header by default. pub fn new() -> GzBuilder { GzBuilder { extra: None, filename: None, comment: None, operating_system: None, mtime: 0, } } /// Configure the `mtime` field in the gzip header. pub fn mtime(mut self, mtime: u32) -> GzBuilder { self.mtime = mtime; self } /// Configure the `operating_system` field in the gzip header. pub fn operating_system(mut self, os: u8) -> GzBuilder { self.operating_system = Some(os); self } /// Configure the `extra` field in the gzip header. pub fn extra>>(mut self, extra: T) -> GzBuilder { self.extra = Some(extra.into()); self } /// Configure the `filename` field in the gzip header. /// /// # Panics /// /// Panics if the `filename` slice contains a zero. pub fn filename>>(mut self, filename: T) -> GzBuilder { self.filename = Some(CString::new(filename.into()).unwrap()); self } /// Configure the `comment` field in the gzip header. /// /// # Panics /// /// Panics if the `comment` slice contains a zero. pub fn comment>>(mut self, comment: T) -> GzBuilder { self.comment = Some(CString::new(comment.into()).unwrap()); self } /// Consume this builder, creating a writer encoder in the process. /// /// The data written to the returned encoder will be compressed and then /// written out to the supplied parameter `w`. pub fn write(self, w: W, lvl: Compression) -> write::GzEncoder { write::gz_encoder(self.into_header(lvl), w, lvl) } /// Consume this builder, creating a reader encoder in the process. /// /// Data read from the returned encoder will be the compressed version of /// the data read from the given reader. pub fn read(self, r: R, lvl: Compression) -> read::GzEncoder { read::gz_encoder(self.buf_read(BufReader::new(r), lvl)) } /// Consume this builder, creating a reader encoder in the process. /// /// Data read from the returned encoder will be the compressed version of /// the data read from the given reader. pub fn buf_read(self, r: R, lvl: Compression) -> bufread::GzEncoder where R: BufRead, { bufread::gz_encoder(self.into_header(lvl), r, lvl) } fn into_header(self, lvl: Compression) -> Vec { let GzBuilder { extra, filename, comment, operating_system, mtime, } = self; let mut flg = 0; let mut header = vec![0u8; 10]; match extra { Some(v) => { flg |= FEXTRA; header.push((v.len() >> 0) as u8); header.push((v.len() >> 8) as u8); header.extend(v); } None => {} } match filename { Some(filename) => { flg |= FNAME; header.extend(filename.as_bytes_with_nul().iter().map(|x| *x)); } None => {} } match comment { Some(comment) => { flg |= FCOMMENT; header.extend(comment.as_bytes_with_nul().iter().map(|x| *x)); } None => {} } header[0] = 0x1f; header[1] = 0x8b; header[2] = 8; header[3] = flg; header[4] = (mtime >> 0) as u8; header[5] = (mtime >> 8) as u8; header[6] = (mtime >> 16) as u8; header[7] = (mtime >> 24) as u8; header[8] = if lvl.0 >= Compression::best().0 { 2 } else if lvl.0 <= Compression::fast().0 { 4 } else { 0 }; // Typically this byte indicates what OS the gz stream was created on, // but in an effort to have cross-platform reproducible streams just // default this value to 255. I'm not sure that if we "correctly" set // this it'd do anything anyway... header[9] = operating_system.unwrap_or(255); return header; } } #[cfg(test)] mod tests { use std::io::prelude::*; use super::{read, write, GzBuilder}; use crate::Compression; use rand::{thread_rng, Rng}; #[test] fn roundtrip() { let mut e = write::GzEncoder::new(Vec::new(), Compression::default()); e.write_all(b"foo bar baz").unwrap(); let inner = e.finish().unwrap(); let mut d = read::GzDecoder::new(&inner[..]); let mut s = String::new(); d.read_to_string(&mut s).unwrap(); assert_eq!(s, "foo bar baz"); } #[test] fn roundtrip_zero() { let e = write::GzEncoder::new(Vec::new(), Compression::default()); let inner = e.finish().unwrap(); let mut d = read::GzDecoder::new(&inner[..]); let mut s = String::new(); d.read_to_string(&mut s).unwrap(); assert_eq!(s, ""); } #[test] fn roundtrip_big() { let mut real = Vec::new(); let mut w = write::GzEncoder::new(Vec::new(), Compression::default()); let v = crate::random_bytes().take(1024).collect::>(); for _ in 0..200 { let to_write = &v[..thread_rng().gen_range(0, v.len())]; real.extend(to_write.iter().map(|x| *x)); w.write_all(to_write).unwrap(); } let result = w.finish().unwrap(); let mut r = read::GzDecoder::new(&result[..]); let mut v = Vec::new(); r.read_to_end(&mut v).unwrap(); assert!(v == real); } #[test] fn roundtrip_big2() { let v = crate::random_bytes().take(1024 * 1024).collect::>(); let mut r = read::GzDecoder::new(read::GzEncoder::new(&v[..], Compression::default())); let mut res = Vec::new(); r.read_to_end(&mut res).unwrap(); assert!(res == v); } #[test] fn fields() { let r = vec![0, 2, 4, 6]; let e = GzBuilder::new() .filename("foo.rs") .comment("bar") .extra(vec![0, 1, 2, 3]) .read(&r[..], Compression::default()); let mut d = read::GzDecoder::new(e); assert_eq!(d.header().unwrap().filename(), Some(&b"foo.rs"[..])); assert_eq!(d.header().unwrap().comment(), Some(&b"bar"[..])); assert_eq!(d.header().unwrap().extra(), Some(&b"\x00\x01\x02\x03"[..])); let mut res = Vec::new(); d.read_to_end(&mut res).unwrap(); assert_eq!(res, vec![0, 2, 4, 6]); } #[test] fn keep_reading_after_end() { let mut e = write::GzEncoder::new(Vec::new(), Compression::default()); e.write_all(b"foo bar baz").unwrap(); let inner = e.finish().unwrap(); let mut d = read::GzDecoder::new(&inner[..]); let mut s = String::new(); d.read_to_string(&mut s).unwrap(); assert_eq!(s, "foo bar baz"); d.read_to_string(&mut s).unwrap(); assert_eq!(s, "foo bar baz"); } #[test] fn qc_reader() { ::quickcheck::quickcheck(test as fn(_) -> _); fn test(v: Vec) -> bool { let r = read::GzEncoder::new(&v[..], Compression::default()); let mut r = read::GzDecoder::new(r); let mut v2 = Vec::new(); r.read_to_end(&mut v2).unwrap(); v == v2 } } #[test] fn flush_after_write() { let mut f = write::GzEncoder::new(Vec::new(), Compression::default()); write!(f, "Hello world").unwrap(); f.flush().unwrap(); } use crate::gz::bufread::tests::BlockingCursor; #[test] // test function read_and_forget of Buffer fn blocked_partial_header_read() { // this is a reader which receives data afterwards let mut r = BlockingCursor::new(); let data = vec![1, 2, 3]; match r.write_all(&data) { Ok(()) => {} _ => { panic!("Unexpected result for write_all"); } } r.set_position(0); // this is unused except for the buffering let mut decoder = read::GzDecoder::new(r); let mut out = Vec::with_capacity(7); match decoder.read(&mut out) { Err(e) => { assert_eq!(e.kind(), std::io::ErrorKind::WouldBlock); } _ => { panic!("Unexpected result for decoder.read"); } } } } flate2-1.0.22/src/gz/read.rs000064400000000000000000000211660072674642500136110ustar 00000000000000use std::io; use std::io::prelude::*; #[cfg(feature = "tokio")] use futures::Poll; #[cfg(feature = "tokio")] use tokio_io::{AsyncRead, AsyncWrite}; use super::bufread; use super::{GzBuilder, GzHeader}; use crate::bufreader::BufReader; use crate::Compression; /// A gzip streaming encoder /// /// This structure exposes a [`Read`] interface that will read uncompressed data /// from the underlying reader and expose the compressed version as a [`Read`] /// interface. /// /// [`Read`]: https://doc.rust-lang.org/std/io/trait.Read.html /// /// # Examples /// /// ``` /// use std::io::prelude::*; /// use std::io; /// use flate2::Compression; /// use flate2::read::GzEncoder; /// /// // Return a vector containing the GZ compressed version of hello world /// /// fn gzencode_hello_world() -> io::Result> { /// let mut ret_vec = [0;100]; /// 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()) /// } /// ``` #[derive(Debug)] pub struct GzEncoder { inner: bufread::GzEncoder>, } pub fn gz_encoder(inner: bufread::GzEncoder>) -> GzEncoder { GzEncoder { inner: inner } } impl GzEncoder { /// Creates a new encoder which will use the given compression level. /// /// The encoder is not configured specially for the emitted header. For /// header configuration, see the `GzBuilder` type. /// /// The data read from the stream `r` will be compressed and available /// through the returned reader. pub fn new(r: R, level: Compression) -> GzEncoder { GzBuilder::new().read(r, level) } } impl GzEncoder { /// Acquires a reference to the underlying reader. pub fn get_ref(&self) -> &R { self.inner.get_ref().get_ref() } /// Acquires a mutable reference to the underlying reader. /// /// Note that mutation of the reader may result in surprising results if /// this encoder is continued to be used. pub fn get_mut(&mut self) -> &mut R { self.inner.get_mut().get_mut() } /// Returns the underlying stream, consuming this encoder pub fn into_inner(self) -> R { self.inner.into_inner().into_inner() } } impl Read for GzEncoder { fn read(&mut self, into: &mut [u8]) -> io::Result { self.inner.read(into) } } impl Write for GzEncoder { fn write(&mut self, buf: &[u8]) -> io::Result { self.get_mut().write(buf) } fn flush(&mut self) -> io::Result<()> { self.get_mut().flush() } } /// A gzip streaming decoder /// /// This structure exposes a [`Read`] interface that will consume compressed /// data from the underlying reader and emit uncompressed data. /// /// [`Read`]: https://doc.rust-lang.org/std/io/trait.Read.html /// /// # Examples /// /// ``` /// /// use std::io::prelude::*; /// use std::io; /// # use flate2::Compression; /// # use flate2::write::GzEncoder; /// use flate2::read::GzDecoder; /// /// # fn main() { /// # let mut e = GzEncoder::new(Vec::new(), Compression::default()); /// # e.write_all(b"Hello World").unwrap(); /// # let bytes = e.finish().unwrap(); /// # println!("{}", decode_reader(bytes).unwrap()); /// # } /// # /// // Uncompresses a Gz Encoded vector of bytes and returns a string or error /// // Here &[u8] implements Read /// /// fn decode_reader(bytes: Vec) -> io::Result { /// let mut gz = GzDecoder::new(&bytes[..]); /// let mut s = String::new(); /// gz.read_to_string(&mut s)?; /// Ok(s) /// } /// ``` #[derive(Debug)] pub struct GzDecoder { inner: bufread::GzDecoder>, } impl GzDecoder { /// Creates a new decoder from the given reader, immediately parsing the /// gzip header. pub fn new(r: R) -> GzDecoder { GzDecoder { inner: bufread::GzDecoder::new(BufReader::new(r)), } } } impl GzDecoder { /// Returns the header associated with this stream, if it was valid. pub fn header(&self) -> Option<&GzHeader> { self.inner.header() } /// Acquires a reference to the underlying reader. pub fn get_ref(&self) -> &R { self.inner.get_ref().get_ref() } /// Acquires a mutable reference to the underlying stream. /// /// Note that mutation of the stream may result in surprising results if /// this encoder is continued to be used. pub fn get_mut(&mut self) -> &mut R { self.inner.get_mut().get_mut() } /// Consumes this decoder, returning the underlying reader. pub fn into_inner(self) -> R { self.inner.into_inner().into_inner() } } impl Read for GzDecoder { fn read(&mut self, into: &mut [u8]) -> io::Result { self.inner.read(into) } } #[cfg(feature = "tokio")] impl AsyncRead for GzDecoder {} impl Write for GzDecoder { fn write(&mut self, buf: &[u8]) -> io::Result { self.get_mut().write(buf) } fn flush(&mut self) -> io::Result<()> { self.get_mut().flush() } } #[cfg(feature = "tokio")] impl AsyncWrite for GzDecoder { fn shutdown(&mut self) -> Poll<(), io::Error> { self.get_mut().shutdown() } } /// A gzip streaming decoder that decodes all members of a multistream /// /// 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 /// first gzip member. The multistream format is commonly used in bioinformatics, /// for example when using the BGZF compressed data. /// /// This structure exposes a [`Read`] interface that will consume all gzip members /// from the underlying reader and emit uncompressed data. /// /// [`Read`]: https://doc.rust-lang.org/std/io/trait.Read.html /// /// # Examples /// /// ``` /// use std::io::prelude::*; /// use std::io; /// # use flate2::Compression; /// # use flate2::write::GzEncoder; /// use flate2::read::MultiGzDecoder; /// /// # fn main() { /// # let mut e = GzEncoder::new(Vec::new(), Compression::default()); /// # e.write_all(b"Hello World").unwrap(); /// # let bytes = e.finish().unwrap(); /// # println!("{}", decode_reader(bytes).unwrap()); /// # } /// # /// // Uncompresses a Gz Encoded vector of bytes and returns a string or error /// // Here &[u8] implements Read /// /// fn decode_reader(bytes: Vec) -> io::Result { /// let mut gz = MultiGzDecoder::new(&bytes[..]); /// let mut s = String::new(); /// gz.read_to_string(&mut s)?; /// Ok(s) /// } /// ``` #[derive(Debug)] pub struct MultiGzDecoder { inner: bufread::MultiGzDecoder>, } impl MultiGzDecoder { /// Creates a new decoder from the given reader, immediately parsing the /// (first) gzip header. If the gzip stream contains multiple members all will /// be decoded. pub fn new(r: R) -> MultiGzDecoder { MultiGzDecoder { inner: bufread::MultiGzDecoder::new(BufReader::new(r)), } } } impl MultiGzDecoder { /// Returns the current header associated with this stream, if it's valid. pub fn header(&self) -> Option<&GzHeader> { self.inner.header() } /// Acquires a reference to the underlying reader. pub fn get_ref(&self) -> &R { self.inner.get_ref().get_ref() } /// Acquires a mutable reference to the underlying stream. /// /// Note that mutation of the stream may result in surprising results if /// this encoder is continued to be used. pub fn get_mut(&mut self) -> &mut R { self.inner.get_mut().get_mut() } /// Consumes this decoder, returning the underlying reader. pub fn into_inner(self) -> R { self.inner.into_inner().into_inner() } } impl Read for MultiGzDecoder { fn read(&mut self, into: &mut [u8]) -> io::Result { self.inner.read(into) } } #[cfg(feature = "tokio")] impl AsyncRead for MultiGzDecoder {} impl Write for MultiGzDecoder { fn write(&mut self, buf: &[u8]) -> io::Result { self.get_mut().write(buf) } fn flush(&mut self) -> io::Result<()> { self.get_mut().flush() } } #[cfg(feature = "tokio")] impl AsyncWrite for MultiGzDecoder { fn shutdown(&mut self) -> Poll<(), io::Error> { self.get_mut().shutdown() } } flate2-1.0.22/src/gz/write.rs000064400000000000000000000365450072674642500140370ustar 00000000000000use std::cmp; use std::io; use std::io::prelude::*; #[cfg(feature = "tokio")] use futures::Poll; #[cfg(feature = "tokio")] use tokio_io::{AsyncRead, AsyncWrite}; use super::bufread::{corrupt, read_gz_header}; use super::{GzBuilder, GzHeader}; use crate::crc::{Crc, CrcWriter}; use crate::zio; use crate::{Compress, Compression, Decompress, Status}; /// A gzip streaming encoder /// /// This structure exposes a [`Write`] interface that will emit compressed data /// to the underlying writer `W`. /// /// [`Write`]: https://doc.rust-lang.org/std/io/trait.Write.html /// /// # Examples /// /// ``` /// use std::io::prelude::*; /// use flate2::Compression; /// use flate2::write::GzEncoder; /// /// // Vec implements Write to print the compressed bytes of sample string /// # fn main() { /// /// let mut e = GzEncoder::new(Vec::new(), Compression::default()); /// e.write_all(b"Hello World").unwrap(); /// println!("{:?}", e.finish().unwrap()); /// # } /// ``` #[derive(Debug)] pub struct GzEncoder { inner: zio::Writer, crc: Crc, crc_bytes_written: usize, header: Vec, } pub fn gz_encoder(header: Vec, w: W, lvl: Compression) -> GzEncoder { GzEncoder { inner: zio::Writer::new(w, Compress::new(lvl, false)), crc: Crc::new(), header: header, crc_bytes_written: 0, } } impl GzEncoder { /// Creates a new encoder which will use the given compression level. /// /// The encoder is not configured specially for the emitted header. For /// header configuration, see the `GzBuilder` type. /// /// The data written to the returned encoder will be compressed and then /// written to the stream `w`. pub fn new(w: W, level: Compression) -> GzEncoder { GzBuilder::new().write(w, level) } /// Acquires a reference to the underlying writer. pub fn get_ref(&self) -> &W { self.inner.get_ref() } /// Acquires a mutable reference to the underlying writer. /// /// Note that mutation of the writer may result in surprising results if /// this encoder is continued to be used. pub fn get_mut(&mut self) -> &mut W { self.inner.get_mut() } /// Attempt to finish this output stream, writing out final chunks of data. /// /// Note that this function can only be used once data has finished being /// written to the output stream. After this function is called then further /// calls to `write` may result in a panic. /// /// # Panics /// /// Attempts to write data to this stream may result in a panic after this /// function is called. /// /// # Errors /// /// This function will perform I/O to complete this stream, and any I/O /// errors which occur will be returned from this function. pub fn try_finish(&mut self) -> io::Result<()> { self.write_header()?; self.inner.finish()?; while self.crc_bytes_written < 8 { let (sum, amt) = (self.crc.sum() as u32, self.crc.amount()); let buf = [ (sum >> 0) as u8, (sum >> 8) as u8, (sum >> 16) as u8, (sum >> 24) as u8, (amt >> 0) as u8, (amt >> 8) as u8, (amt >> 16) as u8, (amt >> 24) as u8, ]; let inner = self.inner.get_mut(); let n = inner.write(&buf[self.crc_bytes_written..])?; self.crc_bytes_written += n; } Ok(()) } /// Finish encoding this stream, returning the underlying writer once the /// encoding is done. /// /// Note that this function may not be suitable to call in a situation where /// the underlying stream is an asynchronous I/O stream. To finish a stream /// the `try_finish` (or `shutdown`) method should be used instead. To /// re-acquire ownership of a stream it is safe to call this method after /// `try_finish` or `shutdown` has returned `Ok`. /// /// # Errors /// /// This function will perform I/O to complete this stream, and any I/O /// errors which occur will be returned from this function. pub fn finish(mut self) -> io::Result { self.try_finish()?; Ok(self.inner.take_inner()) } fn write_header(&mut self) -> io::Result<()> { while self.header.len() > 0 { let n = self.inner.get_mut().write(&self.header)?; self.header.drain(..n); } Ok(()) } } impl Write for GzEncoder { fn write(&mut self, buf: &[u8]) -> io::Result { assert_eq!(self.crc_bytes_written, 0); self.write_header()?; let n = self.inner.write(buf)?; self.crc.update(&buf[..n]); Ok(n) } fn flush(&mut self) -> io::Result<()> { assert_eq!(self.crc_bytes_written, 0); self.write_header()?; self.inner.flush() } } #[cfg(feature = "tokio")] impl AsyncWrite for GzEncoder { fn shutdown(&mut self) -> Poll<(), io::Error> { self.try_finish()?; self.get_mut().shutdown() } } impl Read for GzEncoder { fn read(&mut self, buf: &mut [u8]) -> io::Result { self.get_mut().read(buf) } } #[cfg(feature = "tokio")] impl AsyncRead for GzEncoder {} impl Drop for GzEncoder { fn drop(&mut self) { if self.inner.is_present() { let _ = self.try_finish(); } } } /// A gzip streaming decoder /// /// This structure exposes a [`Write`] interface that will emit compressed data /// to the underlying writer `W`. /// /// [`Write`]: https://doc.rust-lang.org/std/io/trait.Write.html /// /// # Examples /// /// ``` /// use std::io::prelude::*; /// use std::io; /// use flate2::Compression; /// use flate2::write::{GzEncoder, GzDecoder}; /// /// # fn main() { /// # let mut e = GzEncoder::new(Vec::new(), Compression::default()); /// # e.write(b"Hello World").unwrap(); /// # let bytes = e.finish().unwrap(); /// # assert_eq!("Hello World", decode_writer(bytes).unwrap()); /// # } /// // Uncompresses a gzip encoded vector of bytes and returns a string or error /// // Here Vec implements Write /// fn decode_writer(bytes: Vec) -> io::Result { /// let mut writer = Vec::new(); /// let mut decoder = GzDecoder::new(writer); /// decoder.write_all(&bytes[..])?; /// writer = decoder.finish()?; /// let return_string = String::from_utf8(writer).expect("String parsing error"); /// Ok(return_string) /// } /// ``` #[derive(Debug)] pub struct GzDecoder { inner: zio::Writer, Decompress>, crc_bytes: Vec, header: Option, header_buf: Vec, } const CRC_BYTES_LEN: usize = 8; impl GzDecoder { /// Creates a new decoder which will write uncompressed data to the stream. /// /// When this encoder is dropped or unwrapped the final pieces of data will /// be flushed. pub fn new(w: W) -> GzDecoder { GzDecoder { inner: zio::Writer::new(CrcWriter::new(w), Decompress::new(false)), crc_bytes: Vec::with_capacity(CRC_BYTES_LEN), header: None, header_buf: Vec::new(), } } /// Returns the header associated with this stream. pub fn header(&self) -> Option<&GzHeader> { self.header.as_ref() } /// Acquires a reference to the underlying writer. pub fn get_ref(&self) -> &W { self.inner.get_ref().get_ref() } /// Acquires a mutable reference to the underlying writer. /// /// Note that mutating the output/input state of the stream may corrupt this /// object, so care must be taken when using this method. pub fn get_mut(&mut self) -> &mut W { self.inner.get_mut().get_mut() } /// Attempt to finish this output stream, writing out final chunks of data. /// /// Note that this function can only be used once data has finished being /// written to the output stream. After this function is called then further /// calls to `write` may result in a panic. /// /// # Panics /// /// Attempts to write data to this stream may result in a panic after this /// function is called. /// /// # Errors /// /// This function will perform I/O to finish the stream, returning any /// errors which happen. pub fn try_finish(&mut self) -> io::Result<()> { self.finish_and_check_crc()?; Ok(()) } /// Consumes this decoder, flushing the output stream. /// /// This will flush the underlying data stream and then return the contained /// writer if the flush succeeded. /// /// Note that this function may not be suitable to call in a situation where /// the underlying stream is an asynchronous I/O stream. To finish a stream /// the `try_finish` (or `shutdown`) method should be used instead. To /// re-acquire ownership of a stream it is safe to call this method after /// `try_finish` or `shutdown` has returned `Ok`. /// /// # Errors /// /// This function will perform I/O to complete this stream, and any I/O /// errors which occur will be returned from this function. pub fn finish(mut self) -> io::Result { self.finish_and_check_crc()?; Ok(self.inner.take_inner().into_inner()) } fn finish_and_check_crc(&mut self) -> io::Result<()> { self.inner.finish()?; if self.crc_bytes.len() != 8 { return Err(corrupt()); } let crc = ((self.crc_bytes[0] as u32) << 0) | ((self.crc_bytes[1] as u32) << 8) | ((self.crc_bytes[2] as u32) << 16) | ((self.crc_bytes[3] as u32) << 24); let amt = ((self.crc_bytes[4] as u32) << 0) | ((self.crc_bytes[5] as u32) << 8) | ((self.crc_bytes[6] as u32) << 16) | ((self.crc_bytes[7] as u32) << 24); if crc != self.inner.get_ref().crc().sum() as u32 { return Err(corrupt()); } if amt != self.inner.get_ref().crc().amount() { return Err(corrupt()); } Ok(()) } } struct Counter { inner: T, pos: usize, } impl Read for Counter { fn read(&mut self, buf: &mut [u8]) -> io::Result { let pos = self.inner.read(buf)?; self.pos += pos; Ok(pos) } } impl Write for GzDecoder { fn write(&mut self, buf: &[u8]) -> io::Result { if self.header.is_none() { // trying to avoid buffer usage let (res, pos) = { let mut counter = Counter { inner: self.header_buf.chain(buf), pos: 0, }; let res = read_gz_header(&mut counter); (res, counter.pos) }; match res { Err(err) => { if err.kind() == io::ErrorKind::UnexpectedEof { // not enough data for header, save to the buffer self.header_buf.extend(buf); Ok(buf.len()) } else { Err(err) } } Ok(header) => { self.header = Some(header); let pos = pos - self.header_buf.len(); self.header_buf.truncate(0); Ok(pos) } } } else { let (n, status) = self.inner.write_with_status(buf)?; if status == Status::StreamEnd { if n < buf.len() && self.crc_bytes.len() < 8 { let remaining = buf.len() - n; let crc_bytes = cmp::min(remaining, CRC_BYTES_LEN - self.crc_bytes.len()); self.crc_bytes.extend(&buf[n..n + crc_bytes]); return Ok(n + crc_bytes); } } Ok(n) } } fn flush(&mut self) -> io::Result<()> { self.inner.flush() } } #[cfg(feature = "tokio")] impl AsyncWrite for GzDecoder { fn shutdown(&mut self) -> Poll<(), io::Error> { self.try_finish()?; self.inner.get_mut().get_mut().shutdown() } } impl Read for GzDecoder { fn read(&mut self, buf: &mut [u8]) -> io::Result { self.inner.get_mut().get_mut().read(buf) } } #[cfg(feature = "tokio")] impl AsyncRead for GzDecoder {} #[cfg(test)] mod tests { use super::*; const STR: &'static str = "Hello World Hello World Hello World Hello World Hello World \ Hello World Hello World Hello World Hello World Hello World \ Hello World Hello World Hello World Hello World Hello World \ Hello World Hello World Hello World Hello World Hello World \ Hello World Hello World Hello World Hello World Hello World"; #[test] fn decode_writer_one_chunk() { let mut e = GzEncoder::new(Vec::new(), Compression::default()); e.write(STR.as_ref()).unwrap(); let bytes = e.finish().unwrap(); let mut writer = Vec::new(); let mut decoder = GzDecoder::new(writer); let n = decoder.write(&bytes[..]).unwrap(); decoder.write(&bytes[n..]).unwrap(); decoder.try_finish().unwrap(); writer = decoder.finish().unwrap(); let return_string = String::from_utf8(writer).expect("String parsing error"); assert_eq!(return_string, STR); } #[test] fn decode_writer_partial_header() { let mut e = GzEncoder::new(Vec::new(), Compression::default()); e.write(STR.as_ref()).unwrap(); let bytes = e.finish().unwrap(); let mut writer = Vec::new(); let mut decoder = GzDecoder::new(writer); assert_eq!(decoder.write(&bytes[..5]).unwrap(), 5); let n = decoder.write(&bytes[5..]).unwrap(); if n < bytes.len() - 5 { decoder.write(&bytes[n + 5..]).unwrap(); } writer = decoder.finish().unwrap(); let return_string = String::from_utf8(writer).expect("String parsing error"); assert_eq!(return_string, STR); } #[test] fn decode_writer_exact_header() { let mut e = GzEncoder::new(Vec::new(), Compression::default()); e.write(STR.as_ref()).unwrap(); let bytes = e.finish().unwrap(); let mut writer = Vec::new(); let mut decoder = GzDecoder::new(writer); assert_eq!(decoder.write(&bytes[..10]).unwrap(), 10); decoder.write(&bytes[10..]).unwrap(); writer = decoder.finish().unwrap(); let return_string = String::from_utf8(writer).expect("String parsing error"); assert_eq!(return_string, STR); } #[test] fn decode_writer_partial_crc() { let mut e = GzEncoder::new(Vec::new(), Compression::default()); e.write(STR.as_ref()).unwrap(); let bytes = e.finish().unwrap(); let mut writer = Vec::new(); let mut decoder = GzDecoder::new(writer); let l = bytes.len() - 5; let n = decoder.write(&bytes[..l]).unwrap(); decoder.write(&bytes[n..]).unwrap(); writer = decoder.finish().unwrap(); let return_string = String::from_utf8(writer).expect("String parsing error"); assert_eq!(return_string, STR); } } flate2-1.0.22/src/lib.rs000064400000000000000000000205310072674642500130170ustar 00000000000000//! A DEFLATE-based stream compression/decompression library //! //! This library provides support for compression and decompression of //! DEFLATE-based streams: //! //! * the DEFLATE format itself //! * the zlib format //! * gzip //! //! These three formats are all closely related and largely only differ in their //! headers/footers. This crate has three types in each submodule for dealing //! with these three formats. //! //! # Implementation //! //! In addition to supporting three formats, this crate supports three different //! backends, controlled through this crate's features: //! //! * `default`, or `rust_backend` - this implementation uses the `miniz_oxide` //! crate which is a port of `miniz.c` (below) to Rust. This feature does not //! require a C compiler and only requires Rust code. //! //! * `miniz-sys` - when enabled this feature will enable this crate to instead //! use `miniz.c`, distributed with `miniz-sys`, to implement //! compression/decompression. //! //! * `zlib` - finally, this feature will enable linking against the `libz` //! library, typically found on most Linux systems by default. If the library //! isn't found to already be on the system it will be compiled from source //! (this is a C library). //! //! There's various tradeoffs associated with each implementation, but in //! general you probably won't have to tweak the defaults. The default choice is //! selected to avoid the need for a C compiler at build time. The `miniz-sys` //! feature is largely a historical artifact at this point and is unlikely to be //! needed, and `zlib` is often useful if you're already using `zlib` for other //! C dependencies. The compression ratios and performance of each of these //! feature should be roughly comparable, but you'll likely want to run your own //! tests if you're curious about the performance. //! //! # Organization //! //! This crate consists mainly of three modules, [`read`], [`write`], and //! [`bufread`]. Each module contains a number of types used to encode and //! decode various streams of data. //! //! All types in the [`write`] module work on instances of [`Write`][write], //! whereas all types in the [`read`] module work on instances of //! [`Read`][read] and [`bufread`] works with [`BufRead`][bufread]. If you //! are decoding directly from a `&[u8]`, use the [`bufread`] types. //! //! ``` //! use flate2::write::GzEncoder; //! use flate2::Compression; //! use std::io; //! use std::io::prelude::*; //! //! # fn main() { let _ = run(); } //! # fn run() -> io::Result<()> { //! let mut encoder = GzEncoder::new(Vec::new(), Compression::default()); //! encoder.write_all(b"Example")?; //! # Ok(()) //! # } //! ``` //! //! //! Other various types are provided at the top-level of the crate for //! management and dealing with encoders/decoders. Also note that types which //! operate over a specific trait often implement the mirroring trait as well. //! For example a `flate2::read::DeflateDecoder` *also* implements the //! `Write` trait if `T: Write`. That is, the "dual trait" is forwarded directly //! to the underlying object if available. //! //! [`read`]: read/index.html //! [`bufread`]: bufread/index.html //! [`write`]: write/index.html //! [read]: https://doc.rust-lang.org/std/io/trait.Read.html //! [write]: https://doc.rust-lang.org/std/io/trait.Write.html //! [bufread]: https://doc.rust-lang.org/std/io/trait.BufRead.html //! //! # Async I/O //! //! This crate optionally can support async I/O streams with the [Tokio stack] via //! the `tokio` feature of this crate: //! //! [Tokio stack]: https://tokio.rs/ //! //! ```toml //! flate2 = { version = "0.2", features = ["tokio"] } //! ``` //! //! All methods are internally capable of working with streams that may return //! [`ErrorKind::WouldBlock`] when they're not ready to perform the particular //! operation. //! //! [`ErrorKind::WouldBlock`]: https://doc.rust-lang.org/std/io/enum.ErrorKind.html //! //! Note that care needs to be taken when using these objects, however. The //! Tokio runtime, in particular, requires that data is fully flushed before //! dropping streams. For compatibility with blocking streams all streams are //! flushed/written when they are dropped, and this is not always a suitable //! time to perform I/O. If I/O streams are flushed before drop, however, then //! these operations will be a noop. #![doc(html_root_url = "https://docs.rs/flate2/0.2")] #![deny(missing_docs)] #![deny(missing_debug_implementations)] #![allow(trivial_numeric_casts)] #![cfg_attr(test, deny(warnings))] pub use crate::crc::{Crc, CrcReader, CrcWriter}; pub use crate::gz::GzBuilder; pub use crate::gz::GzHeader; pub use crate::mem::{Compress, CompressError, Decompress, DecompressError, Status}; pub use crate::mem::{FlushCompress, FlushDecompress}; mod bufreader; mod crc; mod deflate; mod ffi; mod gz; mod mem; mod zio; mod zlib; /// Types which operate over [`Read`] streams, both encoders and decoders for /// various formats. /// /// [`Read`]: https://doc.rust-lang.org/std/io/trait.Read.html pub mod read { pub use crate::deflate::read::DeflateDecoder; pub use crate::deflate::read::DeflateEncoder; pub use crate::gz::read::GzDecoder; pub use crate::gz::read::GzEncoder; pub use crate::gz::read::MultiGzDecoder; pub use crate::zlib::read::ZlibDecoder; pub use crate::zlib::read::ZlibEncoder; } /// Types which operate over [`Write`] streams, both encoders and decoders for /// various formats. /// /// [`Write`]: https://doc.rust-lang.org/std/io/trait.Write.html pub mod write { pub use crate::deflate::write::DeflateDecoder; pub use crate::deflate::write::DeflateEncoder; pub use crate::gz::write::GzDecoder; pub use crate::gz::write::GzEncoder; pub use crate::zlib::write::ZlibDecoder; pub use crate::zlib::write::ZlibEncoder; } /// Types which operate over [`BufRead`] streams, both encoders and decoders for /// various formats. /// /// [`BufRead`]: https://doc.rust-lang.org/std/io/trait.BufRead.html pub mod bufread { pub use crate::deflate::bufread::DeflateDecoder; pub use crate::deflate::bufread::DeflateEncoder; pub use crate::gz::bufread::GzDecoder; pub use crate::gz::bufread::GzEncoder; pub use crate::gz::bufread::MultiGzDecoder; pub use crate::zlib::bufread::ZlibDecoder; pub use crate::zlib::bufread::ZlibEncoder; } fn _assert_send_sync() { fn _assert_send_sync() {} _assert_send_sync::>(); _assert_send_sync::>(); _assert_send_sync::>(); _assert_send_sync::>(); _assert_send_sync::>(); _assert_send_sync::>(); _assert_send_sync::>(); _assert_send_sync::>>(); _assert_send_sync::>>(); _assert_send_sync::>>(); _assert_send_sync::>>(); _assert_send_sync::>>(); _assert_send_sync::>>(); } /// When compressing data, the compression level can be specified by a value in /// this enum. #[derive(Copy, Clone, PartialEq, Eq, Debug)] pub struct Compression(u32); impl Compression { /// Creates a new description of the compression level with an explicitly /// specified integer. /// /// The integer here is typically on a scale of 0-9 where 0 means "no /// compression" and 9 means "take as long as you'd like". pub const fn new(level: u32) -> Compression { Compression(level) } /// No compression is to be performed, this may actually inflate data /// slightly when encoding. pub const fn none() -> Compression { Compression(0) } /// Optimize for the best speed of encoding. pub const fn fast() -> Compression { Compression(1) } /// Optimize for the size of data being encoded. pub const fn best() -> Compression { Compression(9) } /// Returns an integer representing the compression level, typically on a /// scale of 0-9 pub fn level(&self) -> u32 { self.0 } } impl Default for Compression { fn default() -> Compression { Compression(6) } } #[cfg(test)] fn random_bytes() -> impl Iterator { use rand::Rng; use std::iter; iter::repeat(()).map(|_| rand::thread_rng().gen()) } flate2-1.0.22/src/mem.rs000064400000000000000000000701570072674642500130400ustar 00000000000000use std::error::Error; use std::fmt; use std::io; use std::slice; use crate::ffi::{self, Backend, Deflate, DeflateBackend, ErrorMessage, Inflate, InflateBackend}; use crate::Compression; /// Raw in-memory compression stream for blocks of data. /// /// This type is the building block for the I/O streams in the rest of this /// crate. It requires more management than the [`Read`]/[`Write`] API but is /// maximally flexible in terms of accepting input from any source and being /// able to produce output to any memory location. /// /// It is recommended to use the I/O stream adaptors over this type as they're /// easier to use. /// /// [`Read`]: https://doc.rust-lang.org/std/io/trait.Read.html /// [`Write`]: https://doc.rust-lang.org/std/io/trait.Write.html #[derive(Debug)] pub struct Compress { inner: Deflate, } /// Raw in-memory decompression stream for blocks of data. /// /// This type is the building block for the I/O streams in the rest of this /// crate. It requires more management than the [`Read`]/[`Write`] API but is /// maximally flexible in terms of accepting input from any source and being /// able to produce output to any memory location. /// /// It is recommended to use the I/O stream adaptors over this type as they're /// easier to use. /// /// [`Read`]: https://doc.rust-lang.org/std/io/trait.Read.html /// [`Write`]: https://doc.rust-lang.org/std/io/trait.Write.html #[derive(Debug)] pub struct Decompress { inner: Inflate, } #[derive(Copy, Clone, PartialEq, Eq, Debug)] /// Values which indicate the form of flushing to be used when compressing /// in-memory data. pub enum FlushCompress { /// A typical parameter for passing to compression/decompression functions, /// this indicates that the underlying stream to decide how much data to /// accumulate before producing output in order to maximize compression. None = ffi::MZ_NO_FLUSH as isize, /// All pending output is flushed to the output buffer and the output is /// aligned on a byte boundary so that the decompressor can get all input /// data available so far. /// /// Flushing may degrade compression for some compression algorithms and so /// it should only be used when necessary. This will complete the current /// deflate block and follow it with an empty stored block. Sync = ffi::MZ_SYNC_FLUSH as isize, /// All pending output is flushed to the output buffer, but the output is /// not aligned to a byte boundary. /// /// All of the input data so far will be available to the decompressor (as /// with `Flush::Sync`. This completes the current deflate block and follows /// it with an empty fixed codes block that is 10 bites long, and it assures /// that enough bytes are output in order for the decompessor to finish the /// block before the empty fixed code block. Partial = ffi::MZ_PARTIAL_FLUSH as isize, /// All output is flushed as with `Flush::Sync` and the compression state is /// reset so decompression can restart from this point if previous /// compressed data has been damaged or if random access is desired. /// /// Using this option too often can seriously degrade compression. Full = ffi::MZ_FULL_FLUSH as isize, /// Pending input is processed and pending output is flushed. /// /// The return value may indicate that the stream is not yet done and more /// data has yet to be processed. Finish = ffi::MZ_FINISH as isize, #[doc(hidden)] _Nonexhaustive, } #[derive(Copy, Clone, PartialEq, Eq, Debug)] /// Values which indicate the form of flushing to be used when /// decompressing in-memory data. pub enum FlushDecompress { /// A typical parameter for passing to compression/decompression functions, /// this indicates that the underlying stream to decide how much data to /// accumulate before producing output in order to maximize compression. None = ffi::MZ_NO_FLUSH as isize, /// All pending output is flushed to the output buffer and the output is /// aligned on a byte boundary so that the decompressor can get all input /// data available so far. /// /// Flushing may degrade compression for some compression algorithms and so /// it should only be used when necessary. This will complete the current /// deflate block and follow it with an empty stored block. Sync = ffi::MZ_SYNC_FLUSH as isize, /// Pending input is processed and pending output is flushed. /// /// The return value may indicate that the stream is not yet done and more /// data has yet to be processed. Finish = ffi::MZ_FINISH as isize, #[doc(hidden)] _Nonexhaustive, } /// The inner state for an error when decompressing #[derive(Debug)] pub(crate) enum DecompressErrorInner { General { msg: ErrorMessage }, NeedsDictionary(u32), } /// Error returned when a decompression object finds that the input stream of /// bytes was not a valid input stream of bytes. #[derive(Debug)] pub struct DecompressError(pub(crate) DecompressErrorInner); impl DecompressError { /// Indicates whether decompression failed due to requiring a dictionary. /// /// The resulting integer is the Adler-32 checksum of the dictionary /// required. pub fn needs_dictionary(&self) -> Option { match self.0 { DecompressErrorInner::NeedsDictionary(adler) => Some(adler), _ => None, } } } #[inline] pub(crate) fn decompress_failed(msg: ErrorMessage) -> Result { Err(DecompressError(DecompressErrorInner::General { msg })) } #[inline] pub(crate) fn decompress_need_dict(adler: u32) -> Result { Err(DecompressError(DecompressErrorInner::NeedsDictionary( adler, ))) } /// Error returned when a compression object is used incorrectly or otherwise /// generates an error. #[derive(Debug)] pub struct CompressError { pub(crate) msg: ErrorMessage, } #[inline] pub(crate) fn compress_failed(msg: ErrorMessage) -> Result { Err(CompressError { msg }) } /// Possible status results of compressing some data or successfully /// decompressing a block of data. #[derive(Copy, Clone, PartialEq, Eq, Debug)] pub enum Status { /// Indicates success. /// /// Means that more input may be needed but isn't available /// and/or there's more output to be written but the output buffer is full. Ok, /// Indicates that forward progress is not possible due to input or output /// buffers being empty. /// /// For compression it means the input buffer needs some more data or the /// output buffer needs to be freed up before trying again. /// /// For decompression this means that more input is needed to continue or /// the output buffer isn't large enough to contain the result. The function /// can be called again after fixing both. BufError, /// Indicates that all input has been consumed and all output bytes have /// been written. Decompression/compression should not be called again. /// /// For decompression with zlib streams the adler-32 of the decompressed /// data has also been verified. StreamEnd, } impl Compress { /// Creates a new object ready for compressing data that it's given. /// /// The `level` argument here indicates what level of compression is going /// to be performed, and the `zlib_header` argument indicates whether the /// output data should have a zlib header or not. pub fn new(level: Compression, zlib_header: bool) -> Compress { Compress { inner: Deflate::make(level, zlib_header, ffi::MZ_DEFAULT_WINDOW_BITS as u8), } } /// Creates a new object ready for compressing data that it's given. /// /// The `level` argument here indicates what level of compression is going /// to be performed, and the `zlib_header` argument indicates whether the /// output data should have a zlib header or not. The `window_bits` parameter /// indicates the base-2 logarithm of the sliding window size and must be /// between 9 and 15. /// /// # Panics /// /// If `window_bits` does not fall into the range 9 ..= 15, /// `new_with_window_bits` will panic. /// /// # Note /// /// This constructor is only available when the `zlib` feature is used. /// Other backends currently do not support custom window bits. #[cfg(feature = "any_zlib")] pub fn new_with_window_bits( level: Compression, zlib_header: bool, window_bits: u8, ) -> Compress { assert!( window_bits > 8 && window_bits < 16, "window_bits must be within 9 ..= 15" ); Compress { inner: Deflate::make(level, zlib_header, window_bits), } } /// Creates a new object ready for compressing data that it's given. /// /// The `level` argument here indicates what level of compression is going /// to be performed. /// /// The Compress object produced by this constructor outputs gzip headers /// for the compressed data. /// /// # Panics /// /// If `window_bits` does not fall into the range 9 ..= 15, /// `new_with_window_bits` will panic. /// /// # Note /// /// This constructor is only available when the `zlib` feature is used. /// Other backends currently do not support gzip headers for Compress. #[cfg(feature = "any_zlib")] pub fn new_gzip(level: Compression, window_bits: u8) -> Compress { assert!( window_bits > 8 && window_bits < 16, "window_bits must be within 9 ..= 15" ); Compress { inner: Deflate::make(level, true, window_bits + 16), } } /// Returns the total number of input bytes which have been processed by /// this compression object. pub fn total_in(&self) -> u64 { self.inner.total_in() } /// Returns the total number of output bytes which have been produced by /// this compression object. pub fn total_out(&self) -> u64 { self.inner.total_out() } /// Specifies the compression dictionary to use. /// /// Returns the Adler-32 checksum of the dictionary. #[cfg(feature = "any_zlib")] pub fn set_dictionary(&mut self, dictionary: &[u8]) -> Result { let stream = &mut *self.inner.inner.stream_wrapper; stream.msg = std::ptr::null_mut(); let rc = unsafe { assert!(dictionary.len() < ffi::uInt::max_value() as usize); ffi::deflateSetDictionary(stream, dictionary.as_ptr(), dictionary.len() as ffi::uInt) }; match rc { ffi::MZ_STREAM_ERROR => compress_failed(self.inner.inner.msg()), ffi::MZ_OK => Ok(stream.adler as u32), c => panic!("unknown return code: {}", c), } } /// Quickly resets this compressor without having to reallocate anything. /// /// This is equivalent to dropping this object and then creating a new one. pub fn reset(&mut self) { self.inner.reset(); } /// Dynamically updates the compression level. /// /// This can be used to switch between compression levels for different /// kinds of data, or it can be used in conjunction with a call to reset /// to reuse the compressor. /// /// This may return an error if there wasn't enough output space to complete /// the compression of the available input data before changing the /// compression level. Flushing the stream before calling this method /// ensures that the function will succeed on the first call. #[cfg(feature = "any_zlib")] pub fn set_level(&mut self, level: Compression) -> Result<(), CompressError> { use libc::c_int; let stream = &mut *self.inner.inner.stream_wrapper; stream.msg = std::ptr::null_mut(); let rc = unsafe { ffi::deflateParams(stream, level.0 as c_int, ffi::MZ_DEFAULT_STRATEGY) }; match rc { ffi::MZ_OK => Ok(()), ffi::MZ_BUF_ERROR => compress_failed(self.inner.inner.msg()), c => panic!("unknown return code: {}", c), } } /// Compresses the input data into the output, consuming only as much /// input as needed and writing as much output as possible. /// /// The flush option can be any of the available `FlushCompress` parameters. /// /// To learn how much data was consumed or how much output was produced, use /// the `total_in` and `total_out` functions before/after this is called. pub fn compress( &mut self, input: &[u8], output: &mut [u8], flush: FlushCompress, ) -> Result { self.inner.compress(input, output, flush) } /// Compresses the input data into the extra space of the output, consuming /// only as much input as needed and writing as much output as possible. /// /// This function has the same semantics as `compress`, except that the /// length of `vec` is managed by this function. This will not reallocate /// the vector provided or attempt to grow it, so space for the output must /// be reserved in the output vector by the caller before calling this /// function. pub fn compress_vec( &mut self, input: &[u8], output: &mut Vec, flush: FlushCompress, ) -> Result { let cap = output.capacity(); let len = output.len(); unsafe { let before = self.total_out(); let ret = { let ptr = output.as_mut_ptr().offset(len as isize); let out = slice::from_raw_parts_mut(ptr, cap - len); self.compress(input, out, flush) }; output.set_len((self.total_out() - before) as usize + len); return ret; } } } impl Decompress { /// Creates a new object ready for decompressing data that it's given. /// /// The `zlib_header` argument indicates whether the input data is expected /// to have a zlib header or not. pub fn new(zlib_header: bool) -> Decompress { Decompress { inner: Inflate::make(zlib_header, ffi::MZ_DEFAULT_WINDOW_BITS as u8), } } /// Creates a new object ready for decompressing data that it's given. /// /// The `zlib_header` argument indicates whether the input data is expected /// to have a zlib header or not. The `window_bits` parameter indicates the /// base-2 logarithm of the sliding window size and must be between 9 and 15. /// /// # Panics /// /// If `window_bits` does not fall into the range 9 ..= 15, /// `new_with_window_bits` will panic. /// /// # Note /// /// This constructor is only available when the `zlib` feature is used. /// Other backends currently do not support custom window bits. #[cfg(feature = "any_zlib")] pub fn new_with_window_bits(zlib_header: bool, window_bits: u8) -> Decompress { assert!( window_bits > 8 && window_bits < 16, "window_bits must be within 9 ..= 15" ); Decompress { inner: Inflate::make(zlib_header, window_bits), } } /// Creates a new object ready for decompressing data that it's given. /// /// The Deompress object produced by this constructor expects gzip headers /// for the compressed data. /// /// # Panics /// /// If `window_bits` does not fall into the range 9 ..= 15, /// `new_with_window_bits` will panic. /// /// # Note /// /// This constructor is only available when the `zlib` feature is used. /// Other backends currently do not support gzip headers for Decompress. #[cfg(feature = "any_zlib")] pub fn new_gzip(window_bits: u8) -> Decompress { assert!( window_bits > 8 && window_bits < 16, "window_bits must be within 9 ..= 15" ); Decompress { inner: Inflate::make(true, window_bits + 16), } } /// Returns the total number of input bytes which have been processed by /// this decompression object. pub fn total_in(&self) -> u64 { self.inner.total_in() } /// Returns the total number of output bytes which have been produced by /// this decompression object. pub fn total_out(&self) -> u64 { self.inner.total_out() } /// Decompresses the input data into the output, consuming only as much /// input as needed and writing as much output as possible. /// /// The flush option can be any of the available `FlushDecompress` parameters. /// /// If the first call passes `FlushDecompress::Finish` it is assumed that /// the input and output buffers are both sized large enough to decompress /// the entire stream in a single call. /// /// A flush value of `FlushDecompress::Finish` indicates that there are no /// more source bytes available beside what's already in the input buffer, /// and the output buffer is large enough to hold the rest of the /// decompressed data. /// /// To learn how much data was consumed or how much output was produced, use /// the `total_in` and `total_out` functions before/after this is called. /// /// # Errors /// /// If the input data to this instance of `Decompress` is not a valid /// zlib/deflate stream then this function may return an instance of /// `DecompressError` to indicate that the stream of input bytes is corrupted. pub fn decompress( &mut self, input: &[u8], output: &mut [u8], flush: FlushDecompress, ) -> Result { self.inner.decompress(input, output, flush) } /// Decompresses the input data into the extra space in the output vector /// specified by `output`. /// /// This function has the same semantics as `decompress`, except that the /// length of `vec` is managed by this function. This will not reallocate /// the vector provided or attempt to grow it, so space for the output must /// be reserved in the output vector by the caller before calling this /// function. /// /// # Errors /// /// If the input data to this instance of `Decompress` is not a valid /// zlib/deflate stream then this function may return an instance of /// `DecompressError` to indicate that the stream of input bytes is corrupted. pub fn decompress_vec( &mut self, input: &[u8], output: &mut Vec, flush: FlushDecompress, ) -> Result { let cap = output.capacity(); let len = output.len(); unsafe { let before = self.total_out(); let ret = { let ptr = output.as_mut_ptr().offset(len as isize); let out = slice::from_raw_parts_mut(ptr, cap - len); self.decompress(input, out, flush) }; output.set_len((self.total_out() - before) as usize + len); return ret; } } /// Specifies the decompression dictionary to use. #[cfg(feature = "any_zlib")] pub fn set_dictionary(&mut self, dictionary: &[u8]) -> Result { let stream = &mut *self.inner.inner.stream_wrapper; stream.msg = std::ptr::null_mut(); let rc = unsafe { assert!(dictionary.len() < ffi::uInt::max_value() as usize); ffi::inflateSetDictionary(stream, dictionary.as_ptr(), dictionary.len() as ffi::uInt) }; match rc { ffi::MZ_STREAM_ERROR => decompress_failed(self.inner.inner.msg()), ffi::MZ_DATA_ERROR => decompress_need_dict(stream.adler as u32), ffi::MZ_OK => Ok(stream.adler as u32), c => panic!("unknown return code: {}", c), } } /// Performs the equivalent of replacing this decompression state with a /// freshly allocated copy. /// /// This function may not allocate memory, though, and attempts to reuse any /// previously existing resources. /// /// The argument provided here indicates whether the reset state will /// attempt to decode a zlib header first or not. pub fn reset(&mut self, zlib_header: bool) { self.inner.reset(zlib_header); } } impl Error for DecompressError {} impl DecompressError { /// Retrieve the implementation's message about why the operation failed, if one exists. pub fn message(&self) -> Option<&str> { match &self.0 { DecompressErrorInner::General { msg } => msg.get(), _ => None, } } } impl From for io::Error { fn from(data: DecompressError) -> io::Error { io::Error::new(io::ErrorKind::Other, data) } } impl fmt::Display for DecompressError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let msg = match &self.0 { DecompressErrorInner::General { msg } => msg.get(), DecompressErrorInner::NeedsDictionary { .. } => Some("requires a dictionary"), }; match msg { Some(msg) => write!(f, "deflate decompression error: {}", msg), None => write!(f, "deflate decompression error"), } } } impl Error for CompressError {} impl CompressError { /// Retrieve the implementation's message about why the operation failed, if one exists. pub fn message(&self) -> Option<&str> { self.msg.get() } } impl From for io::Error { fn from(data: CompressError) -> io::Error { io::Error::new(io::ErrorKind::Other, data) } } impl fmt::Display for CompressError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self.msg.get() { Some(msg) => write!(f, "deflate compression error: {}", msg), None => write!(f, "deflate compression error"), } } } #[cfg(test)] mod tests { use std::io::Write; use crate::write; use crate::{Compression, Decompress, FlushDecompress}; #[cfg(feature = "any_zlib")] use crate::{Compress, FlushCompress}; #[test] fn issue51() { let data = vec![ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xb3, 0xc9, 0x28, 0xc9, 0xcd, 0xb1, 0xe3, 0xe5, 0xb2, 0xc9, 0x48, 0x4d, 0x4c, 0xb1, 0xb3, 0x29, 0xc9, 0x2c, 0xc9, 0x49, 0xb5, 0x33, 0x31, 0x30, 0x51, 0xf0, 0xcb, 0x2f, 0x51, 0x70, 0xcb, 0x2f, 0xcd, 0x4b, 0xb1, 0xd1, 0x87, 0x08, 0xda, 0xe8, 0x83, 0x95, 0x00, 0x95, 0x26, 0xe5, 0xa7, 0x54, 0x2a, 0x24, 0xa5, 0x27, 0xe7, 0xe7, 0xe4, 0x17, 0xd9, 0x2a, 0x95, 0x67, 0x64, 0x96, 0xa4, 0x2a, 0x81, 0x8c, 0x48, 0x4e, 0xcd, 0x2b, 0x49, 0x2d, 0xb2, 0xb3, 0xc9, 0x30, 0x44, 0x37, 0x01, 0x28, 0x62, 0xa3, 0x0f, 0x95, 0x06, 0xd9, 0x05, 0x54, 0x04, 0xe5, 0xe5, 0xa5, 0x67, 0xe6, 0x55, 0xe8, 0x1b, 0xea, 0x99, 0xe9, 0x19, 0x21, 0xab, 0xd0, 0x07, 0xd9, 0x01, 0x32, 0x53, 0x1f, 0xea, 0x3e, 0x00, 0x94, 0x85, 0xeb, 0xe4, 0xa8, 0x00, 0x00, 0x00, ]; let mut decoded = Vec::with_capacity(data.len() * 2); let mut d = Decompress::new(false); // decompressed whole deflate stream assert!(d .decompress_vec(&data[10..], &mut decoded, FlushDecompress::Finish) .is_ok()); // decompress data that has nothing to do with the deflate stream (this // used to panic) drop(d.decompress_vec(&[0], &mut decoded, FlushDecompress::None)); } #[test] fn reset() { let string = "hello world".as_bytes(); let mut zlib = Vec::new(); let mut deflate = Vec::new(); let comp = Compression::default(); write::ZlibEncoder::new(&mut zlib, comp) .write_all(string) .unwrap(); write::DeflateEncoder::new(&mut deflate, comp) .write_all(string) .unwrap(); let mut dst = [0; 1024]; let mut decoder = Decompress::new(true); decoder .decompress(&zlib, &mut dst, FlushDecompress::Finish) .unwrap(); assert_eq!(decoder.total_out(), string.len() as u64); assert!(dst.starts_with(string)); decoder.reset(false); decoder .decompress(&deflate, &mut dst, FlushDecompress::Finish) .unwrap(); assert_eq!(decoder.total_out(), string.len() as u64); assert!(dst.starts_with(string)); } #[cfg(feature = "any_zlib")] #[test] fn set_dictionary_with_zlib_header() { let string = "hello, hello!".as_bytes(); let dictionary = "hello".as_bytes(); let mut encoded = Vec::with_capacity(1024); let mut encoder = Compress::new(Compression::default(), true); let dictionary_adler = encoder.set_dictionary(&dictionary).unwrap(); encoder .compress_vec(string, &mut encoded, FlushCompress::Finish) .unwrap(); assert_eq!(encoder.total_in(), string.len() as u64); assert_eq!(encoder.total_out(), encoded.len() as u64); let mut decoder = Decompress::new(true); let mut decoded = [0; 1024]; let decompress_error = decoder .decompress(&encoded, &mut decoded, FlushDecompress::Finish) .expect_err("decompression should fail due to requiring a dictionary"); let required_adler = decompress_error.needs_dictionary() .expect("the first call to decompress should indicate a dictionary is required along with the required Adler-32 checksum"); assert_eq!(required_adler, dictionary_adler, "the Adler-32 checksum should match the value when the dictionary was set on the compressor"); let actual_adler = decoder.set_dictionary(&dictionary).unwrap(); assert_eq!(required_adler, actual_adler); // Decompress the rest of the input to the remainder of the output buffer let total_in = decoder.total_in(); let total_out = decoder.total_out(); let decompress_result = decoder.decompress( &encoded[total_in as usize..], &mut decoded[total_out as usize..], FlushDecompress::Finish, ); assert!(decompress_result.is_ok()); assert_eq!(&decoded[..decoder.total_out() as usize], string); } #[cfg(feature = "any_zlib")] #[test] fn set_dictionary_raw() { let string = "hello, hello!".as_bytes(); let dictionary = "hello".as_bytes(); let mut encoded = Vec::with_capacity(1024); let mut encoder = Compress::new(Compression::default(), false); encoder.set_dictionary(&dictionary).unwrap(); encoder .compress_vec(string, &mut encoded, FlushCompress::Finish) .unwrap(); assert_eq!(encoder.total_in(), string.len() as u64); assert_eq!(encoder.total_out(), encoded.len() as u64); let mut decoder = Decompress::new(false); decoder.set_dictionary(&dictionary).unwrap(); let mut decoded = [0; 1024]; let decompress_result = decoder.decompress(&encoded, &mut decoded, FlushDecompress::Finish); assert!(decompress_result.is_ok()); assert_eq!(&decoded[..decoder.total_out() as usize], string); } #[cfg(feature = "any_zlib")] #[test] fn test_gzip_flate() { let string = "hello, hello!".as_bytes(); let mut encoded = Vec::with_capacity(1024); let mut encoder = Compress::new_gzip(Compression::default(), 9); encoder .compress_vec(string, &mut encoded, FlushCompress::Finish) .unwrap(); assert_eq!(encoder.total_in(), string.len() as u64); assert_eq!(encoder.total_out(), encoded.len() as u64); let mut decoder = Decompress::new_gzip(9); let mut decoded = [0; 1024]; decoder .decompress(&encoded, &mut decoded, FlushDecompress::Finish) .unwrap(); assert_eq!(&decoded[..decoder.total_out() as usize], string); } #[cfg(feature = "any_zlib")] #[test] fn test_error_message() { let mut decoder = Decompress::new(false); let mut decoded = [0; 128]; let garbage = b"xbvxzi"; let err = decoder .decompress(&*garbage, &mut decoded, FlushDecompress::Finish) .unwrap_err(); assert_eq!(err.message(), Some("invalid stored block lengths")); } } flate2-1.0.22/src/zio.rs000064400000000000000000000175300072674642500130570ustar 00000000000000use std::io; use std::io::prelude::*; use std::mem; use crate::{Compress, Decompress, DecompressError, FlushCompress, FlushDecompress, Status}; #[derive(Debug)] pub struct Writer { obj: Option, pub data: D, buf: Vec, } pub trait Ops { type Flush: Flush; fn total_in(&self) -> u64; fn total_out(&self) -> u64; fn run( &mut self, input: &[u8], output: &mut [u8], flush: Self::Flush, ) -> Result; fn run_vec( &mut self, input: &[u8], output: &mut Vec, flush: Self::Flush, ) -> Result; } impl Ops for Compress { type Flush = FlushCompress; fn total_in(&self) -> u64 { self.total_in() } fn total_out(&self) -> u64 { self.total_out() } fn run( &mut self, input: &[u8], output: &mut [u8], flush: FlushCompress, ) -> Result { Ok(self.compress(input, output, flush).unwrap()) } fn run_vec( &mut self, input: &[u8], output: &mut Vec, flush: FlushCompress, ) -> Result { Ok(self.compress_vec(input, output, flush).unwrap()) } } impl Ops for Decompress { type Flush = FlushDecompress; fn total_in(&self) -> u64 { self.total_in() } fn total_out(&self) -> u64 { self.total_out() } fn run( &mut self, input: &[u8], output: &mut [u8], flush: FlushDecompress, ) -> Result { self.decompress(input, output, flush) } fn run_vec( &mut self, input: &[u8], output: &mut Vec, flush: FlushDecompress, ) -> Result { self.decompress_vec(input, output, flush) } } pub trait Flush { fn none() -> Self; fn sync() -> Self; fn finish() -> Self; } impl Flush for FlushCompress { fn none() -> Self { FlushCompress::None } fn sync() -> Self { FlushCompress::Sync } fn finish() -> Self { FlushCompress::Finish } } impl Flush for FlushDecompress { fn none() -> Self { FlushDecompress::None } fn sync() -> Self { FlushDecompress::Sync } fn finish() -> Self { FlushDecompress::Finish } } pub fn read(obj: &mut R, data: &mut D, dst: &mut [u8]) -> io::Result where R: BufRead, D: Ops, { loop { let (read, consumed, ret, eof); { let input = obj.fill_buf()?; eof = input.is_empty(); let before_out = data.total_out(); let before_in = data.total_in(); let flush = if eof { D::Flush::finish() } else { D::Flush::none() }; ret = data.run(input, dst, flush); read = (data.total_out() - before_out) as usize; consumed = (data.total_in() - before_in) as usize; } obj.consume(consumed); match ret { // If we haven't ready any data and we haven't hit EOF yet, // then we need to keep asking for more data because if we // return that 0 bytes of data have been read then it will // be interpreted as EOF. Ok(Status::Ok) | Ok(Status::BufError) if read == 0 && !eof && dst.len() > 0 => continue, Ok(Status::Ok) | Ok(Status::BufError) | Ok(Status::StreamEnd) => return Ok(read), Err(..) => { return Err(io::Error::new( io::ErrorKind::InvalidInput, "corrupt deflate stream", )) } } } } impl Writer { pub fn new(w: W, d: D) -> Writer { Writer { obj: Some(w), data: d, buf: Vec::with_capacity(32 * 1024), } } pub fn finish(&mut self) -> io::Result<()> { loop { self.dump()?; let before = self.data.total_out(); self.data.run_vec(&[], &mut self.buf, D::Flush::finish())?; if before == self.data.total_out() { return Ok(()); } } } pub fn replace(&mut self, w: W) -> W { self.buf.truncate(0); mem::replace(self.get_mut(), w) } pub fn get_ref(&self) -> &W { self.obj.as_ref().unwrap() } pub fn get_mut(&mut self) -> &mut W { self.obj.as_mut().unwrap() } // Note that this should only be called if the outer object is just about // to be consumed! // // (e.g. an implementation of `into_inner`) pub fn take_inner(&mut self) -> W { self.obj.take().unwrap() } pub fn is_present(&self) -> bool { self.obj.is_some() } // Returns total written bytes and status of underlying codec pub(crate) fn write_with_status(&mut self, buf: &[u8]) -> io::Result<(usize, Status)> { // miniz isn't guaranteed to actually write any of the buffer provided, // it may be in a flushing mode where it's just giving us data before // we're actually giving it any data. We don't want to spuriously return // `Ok(0)` when possible as it will cause calls to write_all() to fail. // As a result we execute this in a loop to ensure that we try our // darndest to write the data. loop { self.dump()?; let before_in = self.data.total_in(); let ret = self.data.run_vec(buf, &mut self.buf, D::Flush::none()); let written = (self.data.total_in() - before_in) as usize; let is_stream_end = match ret { Ok(Status::StreamEnd) => true, _ => false, }; if buf.len() > 0 && written == 0 && ret.is_ok() && !is_stream_end { continue; } return match ret { Ok(st) => match st { Status::Ok | Status::BufError | Status::StreamEnd => Ok((written, st)), }, Err(..) => Err(io::Error::new( io::ErrorKind::InvalidInput, "corrupt deflate stream", )), }; } } fn dump(&mut self) -> io::Result<()> { // TODO: should manage this buffer not with `drain` but probably more of // a deque-like strategy. while self.buf.len() > 0 { let n = self.obj.as_mut().unwrap().write(&self.buf)?; if n == 0 { return Err(io::ErrorKind::WriteZero.into()); } self.buf.drain(..n); } Ok(()) } } impl Write for Writer { fn write(&mut self, buf: &[u8]) -> io::Result { self.write_with_status(buf).map(|res| res.0) } fn flush(&mut self) -> io::Result<()> { self.data .run_vec(&[], &mut self.buf, D::Flush::sync()) .unwrap(); // Unfortunately miniz doesn't actually tell us when we're done with // pulling out all the data from the internal stream. To remedy this we // have to continually ask the stream for more memory until it doesn't // give us a chunk of memory the same size as our own internal buffer, // at which point we assume it's reached the end. loop { self.dump()?; let before = self.data.total_out(); self.data .run_vec(&[], &mut self.buf, D::Flush::none()) .unwrap(); if before == self.data.total_out() { break; } } self.obj.as_mut().unwrap().flush() } } impl Drop for Writer { fn drop(&mut self) { if self.obj.is_some() { let _ = self.finish(); } } } flate2-1.0.22/src/zlib/bufread.rs000064400000000000000000000162630072674642500146300ustar 00000000000000use std::io; use std::io::prelude::*; use std::mem; #[cfg(feature = "tokio")] use futures::Poll; #[cfg(feature = "tokio")] use tokio_io::{AsyncRead, AsyncWrite}; use crate::zio; use crate::{Compress, Decompress}; /// A ZLIB encoder, or compressor. /// /// This structure consumes a [`BufRead`] interface, reading uncompressed data /// from the underlying reader, and emitting compressed data. /// /// [`BufRead`]: https://doc.rust-lang.org/std/io/trait.BufRead.html /// /// # Examples /// /// ``` /// use std::io::prelude::*; /// use flate2::Compression; /// use flate2::bufread::ZlibEncoder; /// use std::fs::File; /// use std::io::BufReader; /// /// // Use a buffered file to compress contents into a Vec /// /// # fn open_hello_world() -> std::io::Result> { /// let f = File::open("examples/hello_world.txt")?; /// let b = BufReader::new(f); /// let mut z = ZlibEncoder::new(b, Compression::fast()); /// let mut buffer = Vec::new(); /// z.read_to_end(&mut buffer)?; /// # Ok(buffer) /// # } /// ``` #[derive(Debug)] pub struct ZlibEncoder { obj: R, data: Compress, } impl ZlibEncoder { /// Creates a new encoder which will read uncompressed data from the given /// stream and emit the compressed stream. pub fn new(r: R, level: crate::Compression) -> ZlibEncoder { ZlibEncoder { obj: r, data: Compress::new(level, true), } } } pub fn reset_encoder_data(zlib: &mut ZlibEncoder) { zlib.data.reset() } impl ZlibEncoder { /// Resets the state of this encoder entirely, swapping out the input /// stream for another. /// /// This function will reset the internal state of this encoder and replace /// the input stream with the one provided, returning the previous input /// stream. Future data read from this encoder will be the compressed /// version of `r`'s data. pub fn reset(&mut self, r: R) -> R { reset_encoder_data(self); mem::replace(&mut self.obj, r) } /// Acquires a reference to the underlying reader pub fn get_ref(&self) -> &R { &self.obj } /// Acquires a mutable reference to the underlying stream /// /// Note that mutation of the stream may result in surprising results if /// this encoder is continued to be used. pub fn get_mut(&mut self) -> &mut R { &mut self.obj } /// Consumes this encoder, returning the underlying reader. pub fn into_inner(self) -> R { self.obj } /// Returns the number of bytes that have been read into this compressor. /// /// Note that not all bytes read from the underlying object may be accounted /// for, there may still be some active buffering. pub fn total_in(&self) -> u64 { self.data.total_in() } /// Returns the number of bytes that the compressor has produced. /// /// Note that not all bytes may have been read yet, some may still be /// buffered. pub fn total_out(&self) -> u64 { self.data.total_out() } } impl Read for ZlibEncoder { fn read(&mut self, buf: &mut [u8]) -> io::Result { zio::read(&mut self.obj, &mut self.data, buf) } } #[cfg(feature = "tokio")] impl AsyncRead for ZlibEncoder {} impl Write for ZlibEncoder { fn write(&mut self, buf: &[u8]) -> io::Result { self.get_mut().write(buf) } fn flush(&mut self) -> io::Result<()> { self.get_mut().flush() } } #[cfg(feature = "tokio")] impl AsyncWrite for ZlibEncoder { fn shutdown(&mut self) -> Poll<(), io::Error> { self.get_mut().shutdown() } } /// A ZLIB decoder, or decompressor. /// /// This structure consumes a [`BufRead`] interface, reading compressed data /// from the underlying reader, and emitting uncompressed data. /// /// [`BufRead`]: https://doc.rust-lang.org/std/io/trait.BufRead.html /// /// # Examples /// /// ``` /// use std::io::prelude::*; /// use std::io; /// # use flate2::Compression; /// # use flate2::write::ZlibEncoder; /// use flate2::bufread::ZlibDecoder; /// /// # fn main() { /// # let mut e = ZlibEncoder::new(Vec::new(), Compression::default()); /// # e.write_all(b"Hello World").unwrap(); /// # let bytes = e.finish().unwrap(); /// # println!("{}", decode_bufreader(bytes).unwrap()); /// # } /// # /// // Uncompresses a Zlib Encoded vector of bytes and returns a string or error /// // Here &[u8] implements BufRead /// /// fn decode_bufreader(bytes: Vec) -> io::Result { /// let mut z = ZlibDecoder::new(&bytes[..]); /// let mut s = String::new(); /// z.read_to_string(&mut s)?; /// Ok(s) /// } /// ``` #[derive(Debug)] pub struct ZlibDecoder { obj: R, data: Decompress, } impl ZlibDecoder { /// Creates a new decoder which will decompress data read from the given /// stream. pub fn new(r: R) -> ZlibDecoder { ZlibDecoder { obj: r, data: Decompress::new(true), } } } pub fn reset_decoder_data(zlib: &mut ZlibDecoder) { zlib.data = Decompress::new(true); } impl ZlibDecoder { /// Resets the state of this decoder entirely, swapping out the input /// stream for another. /// /// This will reset the internal state of this decoder and replace the /// input stream with the one provided, returning the previous input /// stream. Future data read from this decoder will be the decompressed /// version of `r`'s data. pub fn reset(&mut self, r: R) -> R { reset_decoder_data(self); mem::replace(&mut self.obj, r) } /// Acquires a reference to the underlying stream pub fn get_ref(&self) -> &R { &self.obj } /// Acquires a mutable reference to the underlying stream /// /// Note that mutation of the stream may result in surprising results if /// this encoder is continued to be used. pub fn get_mut(&mut self) -> &mut R { &mut self.obj } /// Consumes this decoder, returning the underlying reader. pub fn into_inner(self) -> R { self.obj } /// Returns the number of bytes that the decompressor has consumed. /// /// Note that this will likely be smaller than what the decompressor /// actually read from the underlying stream due to buffering. pub fn total_in(&self) -> u64 { self.data.total_in() } /// Returns the number of bytes that the decompressor has produced. pub fn total_out(&self) -> u64 { self.data.total_out() } } impl Read for ZlibDecoder { fn read(&mut self, into: &mut [u8]) -> io::Result { zio::read(&mut self.obj, &mut self.data, into) } } #[cfg(feature = "tokio")] impl AsyncRead for ZlibDecoder {} impl Write for ZlibDecoder { fn write(&mut self, buf: &[u8]) -> io::Result { self.get_mut().write(buf) } fn flush(&mut self) -> io::Result<()> { self.get_mut().flush() } } #[cfg(feature = "tokio")] impl AsyncWrite for ZlibDecoder { fn shutdown(&mut self) -> Poll<(), io::Error> { self.get_mut().shutdown() } } flate2-1.0.22/src/zlib/mod.rs000064400000000000000000000117110072674642500137700ustar 00000000000000pub mod bufread; pub mod read; pub mod write; #[cfg(test)] mod tests { use std::io; use std::io::prelude::*; use rand::{thread_rng, Rng}; use crate::zlib::{read, write}; use crate::Compression; #[test] fn roundtrip() { let mut real = Vec::new(); let mut w = write::ZlibEncoder::new(Vec::new(), Compression::default()); let v = crate::random_bytes().take(1024).collect::>(); for _ in 0..200 { let to_write = &v[..thread_rng().gen_range(0, v.len())]; real.extend(to_write.iter().map(|x| *x)); w.write_all(to_write).unwrap(); } let result = w.finish().unwrap(); let mut r = read::ZlibDecoder::new(&result[..]); let mut ret = Vec::new(); r.read_to_end(&mut ret).unwrap(); assert!(ret == real); } #[test] fn drop_writes() { let mut data = Vec::new(); write::ZlibEncoder::new(&mut data, Compression::default()) .write_all(b"foo") .unwrap(); let mut r = read::ZlibDecoder::new(&data[..]); let mut ret = Vec::new(); r.read_to_end(&mut ret).unwrap(); assert!(ret == b"foo"); } #[test] fn total_in() { let mut real = Vec::new(); let mut w = write::ZlibEncoder::new(Vec::new(), Compression::default()); let v = crate::random_bytes().take(1024).collect::>(); for _ in 0..200 { let to_write = &v[..thread_rng().gen_range(0, v.len())]; real.extend(to_write.iter().map(|x| *x)); w.write_all(to_write).unwrap(); } let mut result = w.finish().unwrap(); let result_len = result.len(); for _ in 0..200 { result.extend(v.iter().map(|x| *x)); } let mut r = read::ZlibDecoder::new(&result[..]); let mut ret = Vec::new(); r.read_to_end(&mut ret).unwrap(); assert!(ret == real); assert_eq!(r.total_in(), result_len as u64); } #[test] fn roundtrip2() { let v = crate::random_bytes().take(1024 * 1024).collect::>(); let mut r = read::ZlibDecoder::new(read::ZlibEncoder::new(&v[..], Compression::default())); let mut ret = Vec::new(); r.read_to_end(&mut ret).unwrap(); assert_eq!(ret, v); } #[test] fn roundtrip3() { let v = crate::random_bytes().take(1024 * 1024).collect::>(); let mut w = write::ZlibEncoder::new(write::ZlibDecoder::new(Vec::new()), Compression::default()); w.write_all(&v).unwrap(); let w = w.finish().unwrap().finish().unwrap(); assert!(w == v); } #[test] fn reset_decoder() { let v = crate::random_bytes().take(1024 * 1024).collect::>(); let mut w = write::ZlibEncoder::new(Vec::new(), Compression::default()); w.write_all(&v).unwrap(); let data = w.finish().unwrap(); { let (mut a, mut b, mut c) = (Vec::new(), Vec::new(), Vec::new()); let mut r = read::ZlibDecoder::new(&data[..]); r.read_to_end(&mut a).unwrap(); r.reset(&data); r.read_to_end(&mut b).unwrap(); let mut r = read::ZlibDecoder::new(&data[..]); r.read_to_end(&mut c).unwrap(); assert!(a == b && b == c && c == v); } { let mut w = write::ZlibDecoder::new(Vec::new()); w.write_all(&data).unwrap(); let a = w.reset(Vec::new()).unwrap(); w.write_all(&data).unwrap(); let b = w.finish().unwrap(); let mut w = write::ZlibDecoder::new(Vec::new()); w.write_all(&data).unwrap(); let c = w.finish().unwrap(); assert!(a == b && b == c && c == v); } } #[test] fn bad_input() { // regress tests: previously caused a panic on drop let mut out: Vec = Vec::new(); let data: Vec = (0..255).cycle().take(1024).collect(); let mut w = write::ZlibDecoder::new(&mut out); match w.write_all(&data[..]) { Ok(_) => panic!("Expected an error to be returned!"), Err(e) => assert_eq!(e.kind(), io::ErrorKind::InvalidInput), } } #[test] fn qc_reader() { ::quickcheck::quickcheck(test as fn(_) -> _); fn test(v: Vec) -> bool { let mut r = read::ZlibDecoder::new(read::ZlibEncoder::new(&v[..], Compression::default())); let mut v2 = Vec::new(); r.read_to_end(&mut v2).unwrap(); v == v2 } } #[test] fn qc_writer() { ::quickcheck::quickcheck(test as fn(_) -> _); fn test(v: Vec) -> bool { let mut w = write::ZlibEncoder::new( write::ZlibDecoder::new(Vec::new()), Compression::default(), ); w.write_all(&v).unwrap(); v == w.finish().unwrap().finish().unwrap() } } } flate2-1.0.22/src/zlib/read.rs000064400000000000000000000202020072674642500141170ustar 00000000000000use std::io; use std::io::prelude::*; #[cfg(feature = "tokio")] use futures::Poll; #[cfg(feature = "tokio")] use tokio_io::{AsyncRead, AsyncWrite}; use super::bufread; use crate::bufreader::BufReader; /// A ZLIB encoder, or compressor. /// /// This structure implements a [`Read`] interface and will read uncompressed /// data from an underlying stream and emit a stream of compressed data. /// /// [`Read`]: https://doc.rust-lang.org/std/io/trait.Read.html /// /// # Examples /// /// ``` /// use std::io::prelude::*; /// use flate2::Compression; /// use flate2::read::ZlibEncoder; /// use std::fs::File; /// /// // Open example file and compress the contents using Read interface /// /// # 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()) /// # } /// ``` #[derive(Debug)] pub struct ZlibEncoder { inner: bufread::ZlibEncoder>, } impl ZlibEncoder { /// Creates a new encoder which will read uncompressed data from the given /// stream and emit the compressed stream. pub fn new(r: R, level: crate::Compression) -> ZlibEncoder { ZlibEncoder { inner: bufread::ZlibEncoder::new(BufReader::new(r), level), } } } impl ZlibEncoder { /// Resets the state of this encoder entirely, swapping out the input /// stream for another. /// /// This function will reset the internal state of this encoder and replace /// the input stream with the one provided, returning the previous input /// stream. Future data read from this encoder will be the compressed /// version of `r`'s data. /// /// Note that there may be currently buffered data when this function is /// called, and in that case the buffered data is discarded. pub fn reset(&mut self, r: R) -> R { super::bufread::reset_encoder_data(&mut self.inner); self.inner.get_mut().reset(r) } /// Acquires a reference to the underlying stream pub fn get_ref(&self) -> &R { self.inner.get_ref().get_ref() } /// Acquires a mutable reference to the underlying stream /// /// Note that mutation of the stream may result in surprising results if /// this encoder is continued to be used. pub fn get_mut(&mut self) -> &mut R { self.inner.get_mut().get_mut() } /// Consumes this encoder, returning the underlying reader. /// /// Note that there may be buffered bytes which are not re-acquired as part /// of this transition. It's recommended to only call this function after /// EOF has been reached. pub fn into_inner(self) -> R { self.inner.into_inner().into_inner() } /// Returns the number of bytes that have been read into this compressor. /// /// Note that not all bytes read from the underlying object may be accounted /// for, there may still be some active buffering. pub fn total_in(&self) -> u64 { self.inner.total_in() } /// Returns the number of bytes that the compressor has produced. /// /// Note that not all bytes may have been read yet, some may still be /// buffered. pub fn total_out(&self) -> u64 { self.inner.total_out() } } impl Read for ZlibEncoder { fn read(&mut self, buf: &mut [u8]) -> io::Result { self.inner.read(buf) } } #[cfg(feature = "tokio")] impl AsyncRead for ZlibEncoder {} impl Write for ZlibEncoder { fn write(&mut self, buf: &[u8]) -> io::Result { self.get_mut().write(buf) } fn flush(&mut self) -> io::Result<()> { self.get_mut().flush() } } #[cfg(feature = "tokio")] impl AsyncWrite for ZlibEncoder { fn shutdown(&mut self) -> Poll<(), io::Error> { self.get_mut().shutdown() } } /// A ZLIB decoder, or decompressor. /// /// This structure implements a [`Read`] interface and takes a stream of /// compressed data as input, providing the decompressed data when read from. /// /// [`Read`]: https://doc.rust-lang.org/std/io/trait.Read.html /// /// # Examples /// /// ``` /// use std::io::prelude::*; /// use std::io; /// # use flate2::Compression; /// # use flate2::write::ZlibEncoder; /// use flate2::read::ZlibDecoder; /// /// # fn main() { /// # let mut e = ZlibEncoder::new(Vec::new(), Compression::default()); /// # e.write_all(b"Hello World").unwrap(); /// # let bytes = e.finish().unwrap(); /// # println!("{}", decode_reader(bytes).unwrap()); /// # } /// # /// // Uncompresses a Zlib Encoded vector of bytes and returns a string or error /// // Here &[u8] implements Read /// /// fn decode_reader(bytes: Vec) -> io::Result { /// let mut z = ZlibDecoder::new(&bytes[..]); /// let mut s = String::new(); /// z.read_to_string(&mut s)?; /// Ok(s) /// } /// ``` #[derive(Debug)] pub struct ZlibDecoder { inner: bufread::ZlibDecoder>, } impl ZlibDecoder { /// Creates a new decoder which will decompress data read from the given /// stream. pub fn new(r: R) -> ZlibDecoder { ZlibDecoder::new_with_buf(r, vec![0; 32 * 1024]) } /// Same as `new`, but the intermediate buffer for data is specified. /// /// Note that the specified buffer will only be used up to its current /// length. The buffer's capacity will also not grow over time. pub fn new_with_buf(r: R, buf: Vec) -> ZlibDecoder { ZlibDecoder { inner: bufread::ZlibDecoder::new(BufReader::with_buf(buf, r)), } } } impl ZlibDecoder { /// Resets the state of this decoder entirely, swapping out the input /// stream for another. /// /// This will reset the internal state of this decoder and replace the /// input stream with the one provided, returning the previous input /// stream. Future data read from this decoder will be the decompressed /// version of `r`'s data. /// /// Note that there may be currently buffered data when this function is /// called, and in that case the buffered data is discarded. pub fn reset(&mut self, r: R) -> R { super::bufread::reset_decoder_data(&mut self.inner); self.inner.get_mut().reset(r) } /// Acquires a reference to the underlying stream pub fn get_ref(&self) -> &R { self.inner.get_ref().get_ref() } /// Acquires a mutable reference to the underlying stream /// /// Note that mutation of the stream may result in surprising results if /// this encoder is continued to be used. pub fn get_mut(&mut self) -> &mut R { self.inner.get_mut().get_mut() } /// Consumes this decoder, returning the underlying reader. /// /// Note that there may be buffered bytes which are not re-acquired as part /// of this transition. It's recommended to only call this function after /// EOF has been reached. pub fn into_inner(self) -> R { self.inner.into_inner().into_inner() } /// Returns the number of bytes that the decompressor has consumed. /// /// Note that this will likely be smaller than what the decompressor /// actually read from the underlying stream due to buffering. pub fn total_in(&self) -> u64 { self.inner.total_in() } /// Returns the number of bytes that the decompressor has produced. pub fn total_out(&self) -> u64 { self.inner.total_out() } } impl Read for ZlibDecoder { fn read(&mut self, into: &mut [u8]) -> io::Result { self.inner.read(into) } } #[cfg(feature = "tokio")] impl AsyncRead for ZlibDecoder {} impl Write for ZlibDecoder { fn write(&mut self, buf: &[u8]) -> io::Result { self.get_mut().write(buf) } fn flush(&mut self) -> io::Result<()> { self.get_mut().flush() } } #[cfg(feature = "tokio")] impl AsyncWrite for ZlibDecoder { fn shutdown(&mut self) -> Poll<(), io::Error> { self.get_mut().shutdown() } } flate2-1.0.22/src/zlib/write.rs000064400000000000000000000266210072674642500143510ustar 00000000000000use std::io; use std::io::prelude::*; #[cfg(feature = "tokio")] use futures::Poll; #[cfg(feature = "tokio")] use tokio_io::{AsyncRead, AsyncWrite}; use crate::zio; use crate::{Compress, Decompress}; /// A ZLIB encoder, or compressor. /// /// This structure implements a [`Write`] interface and takes a stream of /// uncompressed data, writing the compressed data to the wrapped writer. /// /// [`Write`]: https://doc.rust-lang.org/std/io/trait.Write.html /// /// # Examples /// /// ``` /// use std::io::prelude::*; /// use flate2::Compression; /// use flate2::write::ZlibEncoder; /// /// // Vec implements Write, assigning the compressed bytes of sample string /// /// # fn zlib_encoding() -> std::io::Result<()> { /// let mut e = ZlibEncoder::new(Vec::new(), Compression::default()); /// e.write_all(b"Hello World")?; /// let compressed = e.finish()?; /// # Ok(()) /// # } /// ``` #[derive(Debug)] pub struct ZlibEncoder { inner: zio::Writer, } impl ZlibEncoder { /// Creates a new encoder which will write compressed data to the stream /// given at the given compression level. /// /// When this encoder is dropped or unwrapped the final pieces of data will /// be flushed. pub fn new(w: W, level: crate::Compression) -> ZlibEncoder { ZlibEncoder { inner: zio::Writer::new(w, Compress::new(level, true)), } } /// Acquires a reference to the underlying writer. pub fn get_ref(&self) -> &W { self.inner.get_ref() } /// Acquires a mutable reference to the underlying writer. /// /// Note that mutating the output/input state of the stream may corrupt this /// object, so care must be taken when using this method. pub fn get_mut(&mut self) -> &mut W { self.inner.get_mut() } /// Resets the state of this encoder entirely, swapping out the output /// stream for another. /// /// This function will finish encoding the current stream into the current /// output stream before swapping out the two output streams. /// /// After the current stream has been finished, this will reset the internal /// state of this encoder and replace the output stream with the one /// provided, returning the previous output stream. Future data written to /// this encoder will be the compressed into the stream `w` provided. /// /// # Errors /// /// This function will perform I/O to complete this stream, and any I/O /// errors which occur will be returned from this function. pub fn reset(&mut self, w: W) -> io::Result { self.inner.finish()?; self.inner.data.reset(); Ok(self.inner.replace(w)) } /// Attempt to finish this output stream, writing out final chunks of data. /// /// Note that this function can only be used once data has finished being /// written to the output stream. After this function is called then further /// calls to `write` may result in a panic. /// /// # Panics /// /// Attempts to write data to this stream may result in a panic after this /// function is called. /// /// # Errors /// /// This function will perform I/O to complete this stream, and any I/O /// errors which occur will be returned from this function. pub fn try_finish(&mut self) -> io::Result<()> { self.inner.finish() } /// Consumes this encoder, flushing the output stream. /// /// This will flush the underlying data stream, close off the compressed /// stream and, if successful, return the contained writer. /// /// Note that this function may not be suitable to call in a situation where /// the underlying stream is an asynchronous I/O stream. To finish a stream /// the `try_finish` (or `shutdown`) method should be used instead. To /// re-acquire ownership of a stream it is safe to call this method after /// `try_finish` or `shutdown` has returned `Ok`. /// /// # Errors /// /// This function will perform I/O to complete this stream, and any I/O /// errors which occur will be returned from this function. pub fn finish(mut self) -> io::Result { self.inner.finish()?; Ok(self.inner.take_inner()) } /// Consumes this encoder, flushing the output stream. /// /// This will flush the underlying data stream and then return the contained /// writer if the flush succeeded. /// The compressed stream will not closed but only flushed. This /// means that obtained byte array can by extended by another deflated /// stream. To close the stream add the two bytes 0x3 and 0x0. /// /// # Errors /// /// This function will perform I/O to complete this stream, and any I/O /// errors which occur will be returned from this function. pub fn flush_finish(mut self) -> io::Result { self.inner.flush()?; Ok(self.inner.take_inner()) } /// Returns the number of bytes that have been written to this compresor. /// /// Note that not all bytes written to this object may be accounted for, /// there may still be some active buffering. pub fn total_in(&self) -> u64 { self.inner.data.total_in() } /// Returns the number of bytes that the compressor has produced. /// /// Note that not all bytes may have been written yet, some may still be /// buffered. pub fn total_out(&self) -> u64 { self.inner.data.total_out() } } impl Write for ZlibEncoder { fn write(&mut self, buf: &[u8]) -> io::Result { self.inner.write(buf) } fn flush(&mut self) -> io::Result<()> { self.inner.flush() } } #[cfg(feature = "tokio")] impl AsyncWrite for ZlibEncoder { fn shutdown(&mut self) -> Poll<(), io::Error> { self.try_finish()?; self.get_mut().shutdown() } } impl Read for ZlibEncoder { fn read(&mut self, buf: &mut [u8]) -> io::Result { self.get_mut().read(buf) } } #[cfg(feature = "tokio")] impl AsyncRead for ZlibEncoder {} /// A ZLIB decoder, or decompressor. /// /// This structure implements a [`Write`] and will emit a stream of decompressed /// data when fed a stream of compressed data. /// /// [`Write`]: https://doc.rust-lang.org/std/io/trait.Write.html /// /// # Examples /// /// ``` /// use std::io::prelude::*; /// use std::io; /// # use flate2::Compression; /// # use flate2::write::ZlibEncoder; /// use flate2::write::ZlibDecoder; /// /// # fn main() { /// # let mut e = ZlibEncoder::new(Vec::new(), Compression::default()); /// # e.write_all(b"Hello World").unwrap(); /// # let bytes = e.finish().unwrap(); /// # println!("{}", decode_reader(bytes).unwrap()); /// # } /// # /// // Uncompresses a Zlib Encoded vector of bytes and returns a string or error /// // Here Vec implements Write /// /// fn decode_reader(bytes: Vec) -> io::Result { /// let mut writer = Vec::new(); /// let mut z = ZlibDecoder::new(writer); /// z.write_all(&bytes[..])?; /// writer = z.finish()?; /// let return_string = String::from_utf8(writer).expect("String parsing error"); /// Ok(return_string) /// } /// ``` #[derive(Debug)] pub struct ZlibDecoder { inner: zio::Writer, } impl ZlibDecoder { /// Creates a new decoder which will write uncompressed data to the stream. /// /// When this decoder is dropped or unwrapped the final pieces of data will /// be flushed. pub fn new(w: W) -> ZlibDecoder { ZlibDecoder { inner: zio::Writer::new(w, Decompress::new(true)), } } /// Acquires a reference to the underlying writer. pub fn get_ref(&self) -> &W { self.inner.get_ref() } /// Acquires a mutable reference to the underlying writer. /// /// Note that mutating the output/input state of the stream may corrupt this /// object, so care must be taken when using this method. pub fn get_mut(&mut self) -> &mut W { self.inner.get_mut() } /// Resets the state of this decoder entirely, swapping out the output /// stream for another. /// /// This will reset the internal state of this decoder and replace the /// output stream with the one provided, returning the previous output /// stream. Future data written to this decoder will be decompressed into /// the output stream `w`. /// /// # Errors /// /// This function will perform I/O to complete this stream, and any I/O /// errors which occur will be returned from this function. pub fn reset(&mut self, w: W) -> io::Result { self.inner.finish()?; self.inner.data = Decompress::new(true); Ok(self.inner.replace(w)) } /// Attempt to finish this output stream, writing out final chunks of data. /// /// Note that this function can only be used once data has finished being /// written to the output stream. After this function is called then further /// calls to `write` may result in a panic. /// /// # Panics /// /// Attempts to write data to this stream may result in a panic after this /// function is called. /// /// # Errors /// /// This function will perform I/O to complete this stream, and any I/O /// errors which occur will be returned from this function. pub fn try_finish(&mut self) -> io::Result<()> { self.inner.finish() } /// Consumes this encoder, flushing the output stream. /// /// This will flush the underlying data stream and then return the contained /// writer if the flush succeeded. /// /// Note that this function may not be suitable to call in a situation where /// the underlying stream is an asynchronous I/O stream. To finish a stream /// the `try_finish` (or `shutdown`) method should be used instead. To /// re-acquire ownership of a stream it is safe to call this method after /// `try_finish` or `shutdown` has returned `Ok`. /// /// # Errors /// /// This function will perform I/O to complete this stream, and any I/O /// errors which occur will be returned from this function. pub fn finish(mut self) -> io::Result { self.inner.finish()?; Ok(self.inner.take_inner()) } /// Returns the number of bytes that the decompressor has consumed for /// decompression. /// /// Note that this will likely be smaller than the number of bytes /// successfully written to this stream due to internal buffering. pub fn total_in(&self) -> u64 { self.inner.data.total_in() } /// Returns the number of bytes that the decompressor has written to its /// output stream. pub fn total_out(&self) -> u64 { self.inner.data.total_out() } } impl Write for ZlibDecoder { fn write(&mut self, buf: &[u8]) -> io::Result { self.inner.write(buf) } fn flush(&mut self) -> io::Result<()> { self.inner.flush() } } #[cfg(feature = "tokio")] impl AsyncWrite for ZlibDecoder { fn shutdown(&mut self) -> Poll<(), io::Error> { self.inner.finish()?; self.inner.get_mut().shutdown() } } impl Read for ZlibDecoder { fn read(&mut self, buf: &mut [u8]) -> io::Result { self.inner.get_mut().read(buf) } } #[cfg(feature = "tokio")] impl AsyncRead for ZlibDecoder {} flate2-1.0.22/tests/async-reader.rs000064400000000000000000000042240072674642500152020ustar 00000000000000extern crate flate2; extern crate futures; extern crate tokio_io; use flate2::read::{GzDecoder, MultiGzDecoder}; use futures::prelude::*; use futures::task; use std::cmp; use std::fs::File; use std::io::{self, Read}; use tokio_io::io::read_to_end; use tokio_io::AsyncRead; struct BadReader { reader: T, x: bool, } impl BadReader { fn new(reader: T) -> BadReader { BadReader { reader, x: true } } } impl Read for BadReader { fn read(&mut self, buf: &mut [u8]) -> io::Result { if self.x { self.x = false; let len = cmp::min(buf.len(), 1); self.reader.read(&mut buf[..len]) } else { self.x = true; Err(io::ErrorKind::WouldBlock.into()) } } } struct AssertAsync(T); impl Read for AssertAsync { fn read(&mut self, buf: &mut [u8]) -> io::Result { self.0.read(buf) } } impl AsyncRead for AssertAsync {} struct AlwaysNotify(T); impl Future for AlwaysNotify { type Item = T::Item; type Error = T::Error; fn poll(&mut self) -> Poll { let ret = self.0.poll(); if let Ok(Async::NotReady) = &ret { task::current().notify(); } ret } } #[test] fn test_gz_asyncread() { let f = File::open("tests/good-file.gz").unwrap(); let fut = read_to_end(AssertAsync(GzDecoder::new(BadReader::new(f))), Vec::new()); let (_, content) = AlwaysNotify(fut).wait().unwrap(); let mut expected = Vec::new(); File::open("tests/good-file.txt") .unwrap() .read_to_end(&mut expected) .unwrap(); assert_eq!(content, expected); } #[test] fn test_multi_gz_asyncread() { let f = File::open("tests/multi.gz").unwrap(); let fut = read_to_end( AssertAsync(MultiGzDecoder::new(BadReader::new(f))), Vec::new(), ); let (_, content) = AlwaysNotify(fut).wait().unwrap(); let mut expected = Vec::new(); File::open("tests/multi.txt") .unwrap() .read_to_end(&mut expected) .unwrap(); assert_eq!(content, expected); } flate2-1.0.22/tests/corrupt-gz-file.bin000064400000000000000000000157300072674642500160060ustar 00000000000000MK. ǿVzR24;1RVAE_~Kۿ~ǯۿϿ_~{ʟmZ'ʊʱZBw\fOQ>cS,Xc4޷>c)Om e4!4JzSsڶ51xQkS9%?s*̹hH9gG*9vS1w*SujdmcNM]R{‡f>AOU)t-Ijs6-[CZ>e~{+QViõ6nhYu$-O#7L1XNMkusӾkU0LmV7Tۨ-wƶj3k,M=ƶ֘o۪\e=cW6b!I񅼲SҮ7Ϸvj>WweOh2ϕSS8zy}]Ƨq{EאӶkJ+{ZvmKP>^}?{cվi'K'͚F h1"ruj2uuhAy1v}&AO4Xy4g~vuuE"hciQ4 nddŘzb3FiZCQ[<1KMK. ǿVzR24;1RVAE_~Kۿ~ǯۿϿ_~{ʟmZ'ʊʱZBw\fOQ>cS,Xc4޷>c)Om e4!4JzSsڶ51xQkS9%?s*̹hH9gG*9vS1w*SujdmcNM]R{‡f>AOU)t-Ijs6-[CZ>e~{+QViõ6nhYu$-O#7L1XNMkusӾkU0LmV7Tۨ-wƶj3k,M=ƶ֘o۪\e=cW6b!I񅼲SҮ7Ϸvj>WweOh2ϕSS8zy}]Ƨq{EאӶkJ+{ZvmKP>^}?{cվi'K'͚F h1"ruj2uuhAy1v}&AO4Xy4g~vuuE"hciQ4 nddŘzb3FiZCQ[<1KW6m)]B#()oJxhzkkFu@$mK" d @Z˶6 Rp[< ַm+lwKaC(bk1LЉ)A3Ɂa5 D2'JkWDRaH.EH$,I-8+uIHe3^YHr!rdBSwe,݈i0ē M,a6r0*?ej l[Z#6"aY#+,d9^7M82]JS_ZI1#k 굅ԉC\BGNT:Wh{f'wY7߸u~Ɠ˺5wZlYWk ͜zc?YHJivy5Cƴ]/:Hv{5-b:`Sot0@P,smu汹:-bmR.8kXih#e%Yj F ְfcF, ڣYt2Ԉ@gfpU]xYl>Z9:O%ŶRҝX:͜4CJGZ#)©|+o'vkCLZ`^?$}/b7KQSThux=rJw}ۛ)gX/Ȧmp vFgRv\suMn9Ub@IpIn5+N;)N:y(wP@U5dWS=u<;tDVF%:%[' ?/QXdIUXKv¢~xDՙ+_R #[ .yH0 p=ә@ a8 WApHyu ZO%gb!JA5G'.E{1XlP&ln%؊SeI$CգL#Y*>ږ9+@kY'CΐW(N$5yzt2$*uX- Dn֒pLu~2#A, ~#\N7Xnfc-" w9Y yLo߈iw&Wvq⪾U["789PHM oNl*" 0jTaMͰMvPM=s4ՒtuB8 R=T55R]Œ_W)k]zڈ]b='t$v%V9lˣa*"m寬~p(+:7eO : צ9m LUstE*`X nLϝ  8FVA Ka O|# ڷ8x]& #` )00\D~ h2 & (( zfC+!?bh%SAǁ6Sp1@9j7Qs4ՙmL` ]oX--֪ jZ49ok -a(h C^8豭w_f!8NjGdLe1'[Qa-`>^H~5CouVId#H1w֍/}SpE MCWֶ|!hr@ @'Z0z7 ~Sp.K8(L[-ȻyJUucZqa _űkmGGmd΄TⅬ,TȺMe+E'ִJZ04O(. _KKۅG=Z7c*vezS[|Who(me?bBMŇϓ婬muK@GV?fW0GSqoj*-[3ׇ0(ulu?eHPiTX%)ȦCv@L@Y Dlt'OƂ(d='j(KJ(@cY)jQ5g}$wCo2 V,˷*o׫&l#eZ:CDފv@Fo8(>fd(A]~\+(4g ~62kgq'=J`]p[͙xF$Hxoabkx+y9]w)„J~^eA)e: hmG& t!_G}I^vU =Ǚ~pAlq! Rm.U ]>`5hyg.c=; NY2k$wW˪zXܢ2o .-{eP2nlu}.;XaI:їO & Ja(2 鄌wAOL+RLk bLCgn4]SqqV}󩞺ª1,V JAykkcۏ J66U־.ׇjEyr<_39JpףXkv55+NUaZ 2Q 6p 6&L 'gnOZ]I (n cq^or $X@-*gD-УWhEkBHaY`kڤү`HUPO/U#>\RE/.OMYM D_ECP@ZSyyEsV5Uw S>̫u*GAUwP T~.qm Du0OD]h4УYf g–Qpq ! XUu"Bo[=&U:7|r(mݣK*]i\L?BY=8t/èE[Z8ϣ2P ) >Z @Bb\7lSAe*G!#T;&^oI qT(K998x݉9E\ww>Nkzh#S*$_>U\SØmT(n^֘(\ƭ5ۡ"'ND8{18QZT#L:CԠZ[M& Ȋ6~Ym(pTgl)u-İ=\n @!:!R,; K5?3Sޠ*p8 ]>tEWj8 U1@U-QjZǾa\+NVT c_n0Wξ^@Fپd\}p۾iPNU99B{GkGTW穨l5+?RI = encoder.finish().unwrap(); let mut decoder = flate2::read::DeflateDecoder::new(encoded.as_slice()); assert_eq!(decoder.read(&mut []).unwrap(), 0); let mut decoded = Vec::new(); decoder.read_to_end(&mut decoded).unwrap(); assert_eq!(decoded.as_slice(), original); } #[test] fn deflate_encoder_empty_read() { let original: &[u8] = b"Lorem ipsum dolor sit amet."; let mut encoder = flate2::read::DeflateEncoder::new(original, flate2::Compression::default()); assert_eq!(encoder.read(&mut []).unwrap(), 0); let mut encoded = Vec::new(); encoder.read_to_end(&mut encoded).unwrap(); let mut decoder = flate2::read::DeflateDecoder::new(encoded.as_slice()); let mut decoded = Vec::new(); decoder.read_to_end(&mut decoded).unwrap(); assert_eq!(decoded.as_slice(), original); } #[test] fn gzip_decoder_empty_read() { let original: &[u8] = b"Lorem ipsum dolor sit amet."; let mut encoder = flate2::write::GzEncoder::new(Vec::new(), flate2::Compression::default()); encoder.write_all(original).unwrap(); let encoded: Vec = encoder.finish().unwrap(); let mut decoder = flate2::read::GzDecoder::new(encoded.as_slice()); assert_eq!(decoder.read(&mut []).unwrap(), 0); let mut decoded = Vec::new(); decoder.read_to_end(&mut decoded).unwrap(); assert_eq!(decoded.as_slice(), original); } #[test] fn gzip_encoder_empty_read() { let original: &[u8] = b"Lorem ipsum dolor sit amet."; let mut encoder = flate2::read::GzEncoder::new(original, flate2::Compression::default()); assert_eq!(encoder.read(&mut []).unwrap(), 0); let mut encoded = Vec::new(); encoder.read_to_end(&mut encoded).unwrap(); let mut decoder = flate2::read::GzDecoder::new(encoded.as_slice()); let mut decoded = Vec::new(); decoder.read_to_end(&mut decoded).unwrap(); assert_eq!(decoded.as_slice(), original); } #[test] fn zlib_decoder_empty_read() { let original: &[u8] = b"Lorem ipsum dolor sit amet."; let mut encoder = flate2::write::ZlibEncoder::new(Vec::new(), flate2::Compression::default()); encoder.write_all(original).unwrap(); let encoded: Vec = encoder.finish().unwrap(); let mut decoder = flate2::read::ZlibDecoder::new(encoded.as_slice()); assert_eq!(decoder.read(&mut []).unwrap(), 0); let mut decoded = Vec::new(); decoder.read_to_end(&mut decoded).unwrap(); assert_eq!(decoded.as_slice(), original); } #[test] fn zlib_encoder_empty_read() { let original: &[u8] = b"Lorem ipsum dolor sit amet."; let mut encoder = flate2::read::ZlibEncoder::new(original, flate2::Compression::default()); assert_eq!(encoder.read(&mut []).unwrap(), 0); let mut encoded = Vec::new(); encoder.read_to_end(&mut encoded).unwrap(); let mut decoder = flate2::read::ZlibDecoder::new(encoded.as_slice()); let mut decoded = Vec::new(); decoder.read_to_end(&mut decoded).unwrap(); assert_eq!(decoded.as_slice(), original); } flate2-1.0.22/tests/good-file.gz000064400000000000000000000151560072674642500144740ustar 00000000000000 MK.9n'W@ I(ixpnm7Pw|Ry{Rլ #??ן_߿~/ռS}T הa O0JX>acV~z~iКq a?m5)CYi>gyU?2g(XOeѧOe]T S-0YS,n]KS{kgS+~l1nbц>Ӫԕчv՟_Wmni>G?~6s]:k\{8fS>ni:a]kck~^zlH:[mO;ھh(ٴr?jg݌`3嵔uRVZuG-6bctquwU:ᣳzZ)koS?ı]ʭzfOg|z˷vOXfiz&?m  X)ݟ:'o8vkkLiy{z]WCw׶<^6X#{apxq|Fu?>G[^/qGǬM>og\ 4Я=\?C.?V3n8p}7t)t}c<~ φD#t>-A:s?r"cMb*-O>Ptb+a0*OpںF2mc6]>O`3c:"W(RER{&$dd?LoImFt7=swkAW -7IT }S[<ƃA׻\ol.FW͛:p\ضwH]4X !мd7~F/ oC) ~F }=U߿YAOEY53EXoHq>γ7):DfnM?jf!0DQ"m)s b*bH( hy!JC"!ȵ•'lG~=46/KX̎(y-<}xq BvUXCL YDHw=SRwfi*!'`cI *-`J2ŗ`/` 4 S7H=^PQʶdL窸81H0ȃ]dho@twПG֋I/, al ?vFHγ7lV4l_Ɋ0'()69X l!X)пwHGG h/VAToC@\hlq>wKW榬dqhZ9+U(laO=-I_ڕ_#?t%He^L!PH2Όǂex )vL|׈Z2`}Ļ)F 4eKsHXUR@q RMoMDJH3!eA2 iz @q$qxdfd]?4)+Bb!Ե}!EW`r1<FvVTuqEu]a[ X-=u^vƖl@-)^ʞs 4xL!@l 8I'< RZY2 (#̳" \ϬSCPK63t|H俼P kTd;m҆W{e}1K1^2 ZI n,Qup ^K0V\"t~T -Z` ?j+D\gt-֍![%Dp$sԀu̢_ ht2׌ `@Ap'o_\ .DK8 b9, OxP9B6Y Z#ii%PIp?FF]9@K7" Sih{If ({Ip!ݝ>[% PG I7^ ?ņ8y/J]N,5uOB 2Izr*%4XSFT07:q2`)ZCbqjBίAntvWn!{Gzu|K/u!Q~\zps~o_t}fPqfa2 JkiZA #Qv{Ɋdӣ7 c/Oܳ +YQ, X)-64|(QJ 5u<7^i1 j Ih3}z*2Ϯ[_  H`9{6ѢD$Ţ22p9"=yG?1,,c]ƕ&r'+~PТ)+D{VnEOP&7Q>\/yIS:Cx/J_IXiP>vGfXu6t5 `|Ew oH<`T=v>X% BOoL>BtאBt__Wn;!+/ `RS`4*nRR12 D<}&]Jr]8W̳,L)*[}E)h7k%IiytE4\WDQR[Y(7=$@3 0*C ,x =K⼔,5ic mk'o[7 dt#|(%T_q_>9.7ᕘ $ Q|1r'_ûObAƷH%#Щ7l63n_P.ۏ mn wPwo_ N;كݴkwywJFu^]n|vEIg-ITnZ9@ap˝(=#5ul=aHH1nU4EQ;"8Co)2h撣[ع7dӚ#7=B@ ^1{%,KLDE}FVK0}$GkƜVoF Po5̤nR2a#vgmZdPaQci^tURT{.b]!$i#/ca\m-tP}܆=jް޸21THTwa@3P3N_nN'M ,_SCq|dN)i Ec,B,:ݴʬ2qȔfg*)U0d1':@ks3MP,+|e=ƙEy1'd"ERc>!#%ilIKN_:uG2?Qj9>̯Tg1Blɐ4r}Dg:z wB~(_Y$7˯Q@YJ?OcZKoǟ1ȓgG4'=qLJhx}zPT]9s}ڑɳ@֘[b+1.Qx;EńQ4f՘p1CJi}y%-  S S~㌃17c?QoG-It}9 ]ۙ5_^1JcP"[a{^vySI&U$֌-l`",q28~i87wo10*b~;Xox ޸E*Fw}o@)v4h!8\#ġ'd PztV=c.~bs)uR8t1ߋL]U(dМ'IRO',C|!rU%Y*=:ʫ`ztJuςL KNH˚494y<O즯'"ڣ'G*!ݓAXÎĠ<_}GgQ~f$ۈP8 QJ^ $fn_=4Y)%B6uf-O _XFPqJB46eճ"aV?n̬`'E;czhf4 3q9Jq;3"Y!,fGE3gMl n>B@ϟSЈa]n4ot 20ב㛆Ry@D M+CCdgGG oUɒ" 7KЙ/A&s,@f"R>q0}gjoW+l7xdzSJV^O*3_3F%c+x™HZbޖBLf6Qd?u8Y?M3 C|WXERi1IS{`/#xrKfxĐ. #Y 0/*#ȦbYЅef ԉ,HXQG&M:flate2-1.0.22/tests/good-file.txt000064400000000000000000000350350072674642500146710ustar 00000000000000## ## timestep simulated EIR patent hosts 0 0.136402 16855 1 0.146872 18564 2 0.150157 20334 3 0.146358 22159 4 0.136315 23655 5 0.122354 24848 6 0.104753 25887 7 0.084439 26770 8 0.06417 27238 9 0.0450397 27349 10 0.0295473 27274 11 0.0184662 26909 12 0.0110032 26324 13 0.00634348 25513 14 0.0036144 24469 15 0.00208133 23383 16 0.00122468 22345 17 0.000752514 21342 18 0.000545333 20416 19 0.000546139 19657 20 0.00054572 18806 21 0.000545757 18015 22 0.000545898 17349 23 0.000546719 16594 24 0.000547353 15955 25 0.000547944 15374 26 0.000547606 14765 27 0.000594773 14212 28 0.000969163 13677 29 0.00168295 13180 30 0.003059 12760 31 0.00571599 12313 32 0.0107918 11896 33 0.0201943 11512 34 0.0368013 11340 35 0.0640629 11323 36 0.104447 11769 37 0.157207 12728 38 0.216682 14261 39 0.271159 16491 40 0.303552 19274 41 0.303678 22157 42 0.271945 24875 43 0.215445 27027 44 0.154503 28690 45 0.100717 30046 46 0.0600343 30602 47 0.0328576 30709 48 0.016964 30315 49 0.00841526 29310 50 0.0040958 28058 51 0.0019953 26662 52 0.000986531 25259 53 0.000545786 24049 54 0.000546405 22966 55 0.000546036 21933 56 0.00054427 20953 57 0.000542769 20057 58 0.000541566 19304 59 0.000541822 18477 60 0.000541643 17695 61 0.000541989 17002 62 0.000769298 16391 63 0.00150811 15805 64 0.00295097 15172 65 0.00566197 14690 66 0.0105243 14206 67 0.0186965 13791 68 0.0313363 13470 69 0.0490605 13377 70 0.0711679 13631 71 0.0953625 14209 72 0.118026 15277 73 0.134612 16760 74 0.144311 18339 75 0.146328 20124 76 0.142936 21803 77 0.134029 23435 78 0.120562 24854 79 0.103157 25880 80 0.0834054 26597 81 0.0632474 27226 82 0.0447785 27294 83 0.0295654 27169 84 0.0184081 26803 85 0.0109489 26265 86 0.00631234 25375 87 0.00359978 24306 88 0.00206967 23260 89 0.00122197 22225 90 0.000751031 21277 91 0.000544507 20295 92 0.000543897 19417 93 0.000543483 18623 94 0.000542926 17837 95 0.000542685 17070 96 0.000542387 16424 97 0.000541194 15838 98 0.000540427 15177 99 0.000540774 14608 100 0.000588312 14066 101 0.000959183 13499 102 0.00166774 12979 103 0.00303278 12545 104 0.00567457 12067 105 0.0107272 11712 106 0.0200606 11368 107 0.0364637 11207 108 0.063339 11238 109 0.103717 11660 110 0.156884 12621 111 0.217072 14151 112 0.272311 16358 113 0.305046 19005 114 0.304927 21926 115 0.272427 24662 116 0.216478 27080 117 0.155168 29064 118 0.10079 30370 119 0.0599659 30992 120 0.0331287 30975 121 0.017235 30317 122 0.00860221 29455 123 0.00419286 28172 124 0.00203361 26809 125 0.000998847 25476 126 0.000551418 24230 127 0.000551119 23106 128 0.000552786 22147 129 0.000553814 21183 130 0.000553743 20280 131 0.000554428 19423 132 0.000555022 18598 133 0.000555921 17864 134 0.000556687 17187 135 0.000789996 16527 136 0.00154597 15870 137 0.00302776 15226 138 0.00581484 14685 139 0.010812 14234 140 0.0191832 13818 141 0.0321572 13571 142 0.050328 13538 143 0.072817 13812 144 0.0974321 14368 145 0.120225 15436 146 0.137418 16988 147 0.147086 18775 148 0.149165 20563 149 0.144943 22223 150 0.136631 23741 151 0.123355 24920 152 0.105401 25779 153 0.0851918 26781 154 0.0641702 27265 155 0.0450746 27505 156 0.0294136 27416 157 0.0183811 27028 158 0.0109285 26260 159 0.00634296 25451 160 0.00364513 24472 161 0.0021051 23427 162 0.00123693 22403 163 0.000759531 21393 164 0.000551727 20485 165 0.000552256 19660 166 0.000552303 18862 167 0.000550927 18094 168 0.000551098 17378 169 0.000551093 16691 170 0.000551885 16050 171 0.000552282 15420 172 0.000552591 14878 173 0.00060109 14357 174 0.000980446 13768 175 0.00170301 13241 176 0.003096 12745 177 0.00579971 12294 178 0.010976 11879 179 0.0205422 11636 180 0.0374515 11431 181 0.0649916 11517 182 0.106008 11966 183 0.159983 12918 184 0.221127 14484 185 0.276503 16696 186 0.310316 19518 187 0.311205 22301 188 0.276769 25047 189 0.220506 27360 190 0.159123 29133 191 0.103761 30440 192 0.0613797 31087 193 0.033583 31037 194 0.0173275 30555 195 0.00861968 29617 196 0.00419503 28292 197 0.00203304 26944 198 0.00100126 25569 199 0.000553511 24349 200 0.000554687 23257 201 0.00055586 22204 202 0.000555419 21176 203 0.000556032 20316 204 0.000555974 19509 205 0.000556859 18746 206 0.000556996 17978 207 0.000557102 17288 208 0.000790187 16672 209 0.00154711 16057 210 0.00303521 15449 211 0.00584201 14915 212 0.0108854 14397 213 0.0193386 14010 214 0.0324346 13730 215 0.0507192 13674 216 0.0736661 13874 217 0.0987887 14515 218 0.122411 15693 219 0.139964 17265 220 0.149125 18894 221 0.151434 20662 222 0.148067 22442 223 0.138894 24116 224 0.125436 25367 225 0.107664 26360 226 0.0865709 27044 227 0.0655588 27428 228 0.0459664 27714 229 0.0301384 27687 230 0.0186481 27262 231 0.01103 26677 232 0.00636957 25722 233 0.00366188 24662 234 0.00212213 23575 235 0.00125358 22520 236 0.000768665 21480 237 0.000556393 20563 238 0.000555892 19706 239 0.00055534 18914 240 0.000555027 18165 241 0.000555062 17432 242 0.000553766 16733 243 0.000552984 16070 244 0.000553634 15396 245 0.000554286 14867 246 0.000603759 14362 247 0.000982974 13867 248 0.00170532 13379 249 0.00310471 12907 250 0.00582577 12446 251 0.0110122 12018 252 0.0206284 11730 253 0.0375835 11546 254 0.0652192 11605 255 0.10646 11981 256 0.160858 12949 257 0.223122 14478 258 0.279678 16810 259 0.312171 19452 260 0.311778 22391 261 0.276966 25204 262 0.22251 27379 263 0.159246 29248 264 0.104109 30532 265 0.0617903 30995 266 0.0338421 31042 267 0.0174647 30620 268 0.00867821 29589 269 0.00419968 28293 270 0.00203244 26916 271 0.00100204 25464 272 0.000555586 24219 273 0.000555599 23207 274 0.00055582 22187 275 0.00055516 21136 276 0.000555436 20243 277 0.000555618 19426 278 0.000556778 18635 279 0.000556976 17870 280 0.000557162 17190 281 0.0007904 16506 282 0.00154557 15837 283 0.00302973 15234 284 0.00584543 14717 285 0.0108796 14225 286 0.0192919 13810 287 0.032329 13605 288 0.0505293 13536 289 0.0733417 13760 290 0.0982413 14378 291 0.121477 15400 292 0.138636 17017 293 0.14875 18764 294 0.150515 20516 295 0.146372 22389 296 0.137332 23975 297 0.124076 25120 298 0.106469 26137 299 0.0862987 26973 300 0.0650552 27584 301 0.0456456 27741 302 0.0300744 27565 303 0.0187879 27212 304 0.0112085 26432 305 0.00648306 25501 306 0.00370346 24466 307 0.00213399 23472 308 0.00125463 22415 309 0.000765794 21427 310 0.000552587 20533 311 0.000553175 19632 312 0.000553525 18831 313 0.000554941 18119 314 0.000556327 17336 315 0.000556008 16721 316 0.00055593 16086 317 0.000556421 15516 318 0.000557308 14918 319 0.00060681 14402 320 0.000990746 13849 321 0.00172359 13355 322 0.00313688 12902 323 0.0058708 12425 324 0.0110637 12087 325 0.0206777 11743 326 0.0376394 11531 327 0.0656182 11582 328 0.107414 12034 329 0.162101 12955 330 0.223525 14571 331 0.279935 16842 332 0.314601 19566 333 0.313556 22575 334 0.279571 25279 335 0.221638 27642 336 0.158038 29275 337 0.102505 30638 338 0.0608328 31209 339 0.0335531 31260 340 0.0173332 30520 341 0.00861545 29604 342 0.00419454 28370 343 0.00202587 26940 344 0.000994029 25614 345 0.000549339 24445 346 0.000551477 23239 347 0.000552891 22300 348 0.000551775 21280 349 0.000552425 20424 350 0.000552135 19571 351 0.000552542 18753 352 0.000552863 18058 353 0.000554438 17348 354 0.000786735 16671 355 0.00153958 16047 356 0.00301482 15500 357 0.00580589 14883 358 0.0108227 14347 359 0.0192357 13947 360 0.0321613 13672 361 0.050229 13606 362 0.0729462 13815 363 0.0978564 14566 364 0.120879 15674 365 0.137663 17049 366 0.147092 18813 367 0.150184 20578 368 0.146971 22245 369 0.136769 23723 370 0.12367 24905 371 0.106187 25871 372 0.0860921 26687 373 0.0645899 27375 374 0.0453473 27635 375 0.0298122 27551 376 0.0185448 27134 377 0.0110517 26468 378 0.00640294 25661 379 0.00367011 24653 380 0.00211832 23556 381 0.00125246 22513 382 0.00076891 21568 383 0.000557384 20672 384 0.000557295 19811 385 0.000556837 18982 386 0.000557433 18179 387 0.000557376 17457 388 0.000557751 16720 389 0.000556844 16112 390 0.000555603 15479 391 0.000554871 14809 392 0.00060335 14275 393 0.000982808 13757 394 0.00170757 13221 395 0.00310351 12758 396 0.0058181 12286 397 0.010991 11906 398 0.0205342 11557 399 0.0373486 11393 400 0.0647659 11487 401 0.105589 11887 402 0.15967 12798 403 0.220945 14260 404 0.277122 16477 405 0.310108 19295 406 0.308854 22110 407 0.274911 24915 408 0.218618 27273 409 0.156618 29189 410 0.101775 30572 411 0.0607503 31174 412 0.0334708 31316 413 0.0173443 30731 414 0.00865633 29636 415 0.00421141 28342 416 0.00204387 26991 417 0.00100602 25595 418 0.000555131 24336 419 0.000555037 23251 420 0.000555559 22267 421 0.000554916 21212 422 0.000554432 20306 423 0.000554751 19488 424 0.00055638 18727 425 0.000556727 17927 426 0.000556368 17198 427 0.000788004 16578 428 0.00154404 15944 429 0.00302383 15315 430 0.00582586 14786 431 0.0108457 14290 432 0.0192962 13815 433 0.0323072 13561 434 0.0505101 13456 435 0.0732162 13811 436 0.0978737 14403 437 0.121405 15460 438 0.138202 16993 439 0.1482 18710 440 0.149707 20578 441 0.146945 22256 442 0.137785 23713 443 0.123767 25058 444 0.105989 26087 445 0.085483 26759 446 0.0646144 27375 447 0.0454389 27680 448 0.0299337 27531 449 0.018663 27041 450 0.0111347 26416 451 0.00644197 25614 452 0.00369229 24666 453 0.00211986 23647 454 0.00124761 22650 455 0.000769104 21642 456 0.000558796 20693 457 0.000559908 19746 458 0.000559562 18952 459 0.00056042 18100 460 0.000559447 17401 461 0.000557893 16756 462 0.000557137 16148 463 0.000557269 15504 464 0.000557596 14974 465 0.000606298 14408 466 0.000987712 13909 467 0.00171257 13402 468 0.00311667 12891 469 0.00584794 12433 470 0.0110774 11980 471 0.0207006 11713 472 0.037673 11583 473 0.0654988 11677 474 0.106982 12072 475 0.161926 12898 476 0.224327 14548 477 0.281709 16796 478 0.314567 19512 479 0.313419 22428 480 0.278962 25186 481 0.221864 27755 482 0.158559 29556 483 0.103532 30572 484 0.0611592 31162 485 0.0337539 31197 486 0.0175096 30619 487 0.00865906 29606 488 0.00420125 28271 489 0.00203207 26856 490 0.00100238 25542 491 0.000554405 24306 492 0.00055373 23160 493 0.0005552 22152 494 0.000553776 21192 495 0.000553636 20302 496 0.000553165 19505 497 0.000554014 18719 498 0.00055519 17993 499 0.000556582 17233 500 0.000788165 16569 501 0.00154132 15953 502 0.00302099 15350 503 0.00581186 14752 504 0.0108291 14267 505 0.0192368 13946 506 0.0322191 13677 507 0.0503789 13594 508 0.0730706 13768 509 0.0980646 14416 510 0.121601 15634 511 0.139046 17110 512 0.147779 18876 513 0.149612 20734 514 0.145796 22414 515 0.136936 23884 516 0.123807 25078 517 0.106212 26066 518 0.0855482 26779 519 0.0643386 27340 520 0.0452926 27530 521 0.0298659 27573 522 0.0185447 27169 523 0.0110178 26489 524 0.00635235 25588 525 0.00362881 24549 526 0.00209238 23528 527 0.00123133 22541 528 0.000755917 21498 529 0.000546368 20607 530 0.000547382 19712 531 0.000547084 18975 532 0.000546453 18178 533 0.000546062 17452 534 0.000546085 16749 535 0.000546151 16135 536 0.000545628 15567 537 0.000545969 14968 538 0.000594606 14392 539 0.000968849 13854 540 0.00168489 13360 541 0.00306337 12899 542 0.00573505 12407 543 0.0108348 12017 544 0.02025 11713 545 0.0368201 11517 546 0.0639795 11556 547 0.104882 11941 548 0.158923 12854 549 0.219796 14396 550 0.275801 16733 551 0.307622 19367 552 0.30785 22230 553 0.272898 24873 554 0.217351 27152 555 0.156138 29108 556 0.101477 30379 557 0.0601091 30971 558 0.0331551 31126 559 0.017167 30418 560 0.00853886 29430 561 0.00415201 28190 562 0.00201849 26849 563 0.000991957 25528 564 0.000546751 24180 565 0.00054534 23090 566 0.000544403 22096 567 0.00054368 21140 568 0.000543407 20213 569 0.000544421 19405 570 0.000545241 18625 571 0.000546995 17868 572 0.000547101 17102 573 0.00077428 16423 574 0.00151348 15783 575 0.00296212 15220 576 0.00569555 14602 577 0.0106307 14154 578 0.0188783 13743 579 0.0316572 13538 580 0.0495211 13467 581 0.0718936 13665 582 0.0961304 14240 583 0.119127 15341 584 0.136233 16912 585 0.145327 18567 586 0.146983 20301 587 0.143022 21953 588 0.134931 23439 589 0.121892 24750 590 0.103955 25688 591 0.0833804 26253 592 0.0625106 26918 593 0.0440419 27279 594 0.0290823 27159 595 0.0180758 26786 596 0.0107654 26049 597 0.00622673 25202 598 0.00356716 24168 599 0.00205866 23122 600 0.00121254 22076 601 0.000745744 21100 602 0.000537789 20207 603 0.000537982 19340 604 0.000537795 18527 605 0.000537955 17768 606 0.000539259 17117 607 0.00053942 16425 608 0.000540477 15701 609 0.000540424 15134 610 0.000540084 14558 611 0.00058571 14069 612 0.00095364 13498 613 0.00165505 13054 614 0.00300205 12616 615 0.00561724 12142 616 0.0106079 11720 617 0.0198178 11410 618 0.0360368 11231 619 0.0623418 11314 620 0.101856 11688 621 0.15376 12623 622 0.213046 14078 623 0.267285 16225 624 0.299225 18856 625 0.299517 21756 626 0.26697 24652 627 0.2119 27051 628 0.151393 28925 629 0.098869 30065 630 0.0593653 30570 631 0.0327177 30483 632 0.0170081 29735 633 0.0084493 28844 634 0.00409333 27665 635 0.00197466 26356 636 0.000967996 25009 637 0.000533137 23839 638 0.000532992 22721 639 0.000534258 21676 640 0.000534251 20709 641 0.000534556 19798 642 0.000535287 19008 643 0.000536214 18278 644 0.000536647 17547 645 0.000536556 16901 646 0.000761043 16256 647 0.00149108 15621 648 0.00292808 15032 649 0.0056527 14504 650 0.0105421 14010 651 0.0186823 13646 652 0.0312164 13356 653 0.0485643 13404 654 0.0704061 13612 655 0.0945219 14230 656 0.117178 15374 657 0.134568 16843 658 0.144475 18492 659 0.146915 20238 660 0.14393 21958 661 0.134621 23537 662 0.121737 24773 663 0.104744 25772 664 0.0846226 26427 665 0.0639754 27040 666 0.0448457 27279 667 0.029482 27106 668 0.0183036 26853 669 0.0108721 26178 670 0.00627116 25425 671 0.0035776 24326 672 0.00206466 23279 673 0.00122064 22191 674 0.000751578 21231 675 0.000542574 20323 676 0.000540396 19496 677 0.000538805 18651 678 0.00053881 17920 679 0.000537801 17217 680 0.000537866 16520 681 0.000538522 15876 682 0.000538795 15229 683 0.000539519 14656 684 0.000587348 14121 685 0.000955855 13626 686 0.00165656 13086 687 0.00301095 12666 688 0.00564993 12250 689 0.0106767 11869 690 0.0199729 11524 691 0.03641 11331 692 0.0632378 11402 693 0.103483 11788 694 0.156399 12682 695 0.215591 14337 696 0.269462 16547 697 0.303615 19239 698 0.304506 22023 699 0.273068 24769 700 0.21682 27223 701 0.154934 29029 702 0.100495 30241 703 0.0597382 30801 704 0.0329221 30881 705 0.0170591 30288 706 0.00845353 29329 707 0.00408176 28108 708 0.00198037 26715 709 0.000977102 25340 710 0.000541566 24039 711 0.000542333 22965 712 0.000542417 21858 713 0.000541182 20952 714 0.00054038 20049 715 0.000539725 19192 716 0.000539603 18409 717 0.000539754 17700 718 0.000539679 16960 719 0.000763508 16287 720 0.00149327 15637 721 0.00292609 15057 722 0.00563308 14524 723 0.0104893 14003 724 0.0185874 13625 725 0.0310985 13319 726 0.0487417 13278 727 0.0707124 13502 728 0.0947795 14147 729 0.117155 15183 730 0.133995 16622 flate2-1.0.22/tests/gunzip.rs000064400000000000000000000043670072674642500141510ustar 00000000000000extern crate flate2; use flate2::read::GzDecoder; use flate2::read::MultiGzDecoder; use std::fs::File; use std::io::prelude::*; use std::io::{self, BufReader}; use std::path::Path; // test extraction of a gzipped file #[test] fn test_extract_success() { let content = extract_file(Path::new("tests/good-file.gz")).unwrap(); let mut expected = Vec::new(); File::open("tests/good-file.txt") .unwrap() .read_to_end(&mut expected) .unwrap(); assert!(content == expected); } // // test partial extraction of a multistream gzipped file #[test] fn test_extract_success_partial_multi() { let content = extract_file(Path::new("tests/multi.gz")).unwrap(); let mut expected = String::new(); BufReader::new(File::open("tests/multi.txt").unwrap()) .read_line(&mut expected) .unwrap(); assert_eq!(content, expected.as_bytes()); } // test extraction fails on a corrupt file #[test] fn test_extract_failure() { let result = extract_file(Path::new("tests/corrupt-gz-file.bin")); assert_eq!(result.err().unwrap().kind(), io::ErrorKind::InvalidInput); } //test complete extraction of a multistream gzipped file #[test] fn test_extract_success_multi() { let content = extract_file_multi(Path::new("tests/multi.gz")).unwrap(); let mut expected = Vec::new(); File::open("tests/multi.txt") .unwrap() .read_to_end(&mut expected) .unwrap(); assert_eq!(content, expected); } // Tries to extract path into memory (assuming a .gz file). fn extract_file(path_compressed: &Path) -> io::Result> { let mut v = Vec::new(); let f = File::open(path_compressed)?; GzDecoder::new(f).read_to_end(&mut v)?; Ok(v) } // Tries to extract path into memory (decompressing all members in case // of a multi member .gz file). fn extract_file_multi(path_compressed: &Path) -> io::Result> { let mut v = Vec::new(); let f = File::open(path_compressed)?; MultiGzDecoder::new(f).read_to_end(&mut v)?; Ok(v) } #[test] fn empty_error_once() { let data: &[u8] = &[]; let cbjson = GzDecoder::new(data); let reader = BufReader::new(cbjson); let mut stream = reader.lines(); assert!(stream.next().unwrap().is_err()); assert!(stream.next().is_none()); } flate2-1.0.22/tests/multi.gz000064400000000000000000000000650072674642500137520ustar 000000000000005WK,*.*Jȕ5W+NMK~flate2-1.0.22/tests/multi.txt000064400000000000000000000000150072674642500141440ustar 00000000000000first second flate2-1.0.22/tests/tokio.rs000064400000000000000000000074700072674642500137600ustar 00000000000000#![cfg(feature = "tokio")] extern crate flate2; extern crate futures; extern crate rand; extern crate tokio_io; extern crate tokio_tcp; extern crate tokio_threadpool; use std::io::{Read, Write}; use std::iter; use std::net::{Shutdown, TcpListener}; use std::thread; use flate2::read; use flate2::write; use flate2::Compression; use futures::Future; use rand::{thread_rng, Rng}; use tokio_io::io::{copy, shutdown}; use tokio_io::AsyncRead; use tokio_tcp::TcpStream; #[test] fn tcp_stream_echo_pattern() { const N: u8 = 16; const M: usize = 16 * 1024; let listener = TcpListener::bind("127.0.0.1:0").unwrap(); let addr = listener.local_addr().unwrap(); let t = thread::spawn(move || { let a = listener.accept().unwrap().0; let b = a.try_clone().unwrap(); let t = thread::spawn(move || { let mut b = read::DeflateDecoder::new(b); let mut buf = [0; M]; for i in 0..N { b.read_exact(&mut buf).unwrap(); for byte in buf.iter() { assert_eq!(*byte, i); } } assert_eq!(b.read(&mut buf).unwrap(), 0); }); let mut a = write::ZlibEncoder::new(a, Compression::default()); for i in 0..N { let buf = [i; M]; a.write_all(&buf).unwrap(); } a.finish().unwrap().shutdown(Shutdown::Write).unwrap(); t.join().unwrap(); }); let stream = TcpStream::connect(&addr); let copy = stream .and_then(|s| { let (a, b) = s.split(); let a = read::ZlibDecoder::new(a); let b = write::DeflateEncoder::new(b, Compression::default()); copy(a, b) }) .then(|result| { let (amt, _a, b) = result.unwrap(); assert_eq!(amt, (N as u64) * (M as u64)); shutdown(b).map(|_| ()) }) .map_err(|err| panic!("{}", err)); let threadpool = tokio_threadpool::Builder::new().build(); threadpool.spawn(copy); threadpool.shutdown().wait().unwrap(); t.join().unwrap(); } #[test] fn echo_random() { let v = iter::repeat(()) .take(1024 * 1024) .map(|()| thread_rng().gen::()) .collect::>(); let listener = TcpListener::bind("127.0.0.1:0").unwrap(); let addr = listener.local_addr().unwrap(); let v2 = v.clone(); let t = thread::spawn(move || { let a = listener.accept().unwrap().0; let b = a.try_clone().unwrap(); let mut v3 = v2.clone(); let t = thread::spawn(move || { let mut b = read::DeflateDecoder::new(b); let mut buf = [0; 1024]; while v3.len() > 0 { let n = b.read(&mut buf).unwrap(); for (actual, expected) in buf[..n].iter().zip(&v3) { assert_eq!(*actual, *expected); } v3.drain(..n); } assert_eq!(b.read(&mut buf).unwrap(), 0); }); let mut a = write::ZlibEncoder::new(a, Compression::default()); a.write_all(&v2).unwrap(); a.finish().unwrap().shutdown(Shutdown::Write).unwrap(); t.join().unwrap(); }); let stream = TcpStream::connect(&addr); let copy = stream .and_then(|s| { let (a, b) = s.split(); let a = read::ZlibDecoder::new(a); let b = write::DeflateEncoder::new(b, Compression::default()); copy(a, b) }) .then(move |result| { let (amt, _a, b) = result.unwrap(); assert_eq!(amt, v.len() as u64); shutdown(b).map(|_| ()) }) .map_err(|err| panic!("{}", err)); let threadpool = tokio_threadpool::Builder::new().build(); threadpool.spawn(copy); threadpool.shutdown().wait().unwrap(); t.join().unwrap(); } flate2-1.0.22/tests/zero-write.rs000064400000000000000000000003360072674642500147340ustar 00000000000000extern crate flate2; #[test] fn zero_write_is_error() { let mut buf = [0u8]; let writer = flate2::write::DeflateEncoder::new(&mut buf[..], flate2::Compression::default()); assert!(writer.finish().is_err()); }