Initial vendor packages
Signed-off-by: Valentin Popov <valentin@popov.link>
This commit is contained in:
1
vendor/flate2/.cargo-checksum.json
vendored
Normal file
1
vendor/flate2/.cargo-checksum.json
vendored
Normal file
File diff suppressed because one or more lines are too long
173
vendor/flate2/Cargo.lock
generated
vendored
Normal file
173
vendor/flate2/Cargo.lock
generated
vendored
Normal file
@ -0,0 +1,173 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "adler"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.79"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[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.50"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a31c789563b815f77f4250caee12365734369f942439b7defd71e18a48197130"
|
||||
dependencies = [
|
||||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crc32fast"
|
||||
version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "flate2"
|
||||
version = "1.0.28"
|
||||
dependencies = [
|
||||
"cloudflare-zlib-sys",
|
||||
"crc32fast",
|
||||
"libz-ng-sys",
|
||||
"libz-sys",
|
||||
"miniz_oxide",
|
||||
"quickcheck",
|
||||
"rand",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"wasi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.144"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1"
|
||||
|
||||
[[package]]
|
||||
name = "libz-ng-sys"
|
||||
version = "1.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "425fb6808068335c8c7c69d1cff0a7d1ed8f681e9ac040272f160a89e6f43b8b"
|
||||
dependencies = [
|
||||
"cmake",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libz-sys"
|
||||
version = "1.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "24e6ab01971eb092ffe6a7d42f49f9ff42662f17604681e2843ad65077ba47dc"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"cmake",
|
||||
"libc",
|
||||
"pkg-config",
|
||||
"vcpkg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7"
|
||||
dependencies = [
|
||||
"adler",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pkg-config"
|
||||
version = "0.3.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964"
|
||||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
|
||||
|
||||
[[package]]
|
||||
name = "quickcheck"
|
||||
version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "588f6378e4dd99458b60ec275b4477add41ce4fa9f64dcba6f15adccb19b50d6"
|
||||
dependencies = [
|
||||
"rand",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.8.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"rand_chacha",
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_chacha"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
|
||||
dependencies = [
|
||||
"ppv-lite86",
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "vcpkg"
|
||||
version = "0.2.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.11.0+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
111
vendor/flate2/Cargo.toml
vendored
Normal file
111
vendor/flate2/Cargo.toml
vendored
Normal file
@ -0,0 +1,111 @@
|
||||
# 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.28"
|
||||
authors = [
|
||||
"Alex Crichton <alex@alexcrichton.com>",
|
||||
"Josh Triplett <josh@joshtriplett.org>",
|
||||
]
|
||||
description = """
|
||||
DEFLATE compression and decompression exposed as Read/BufRead/Write streams.
|
||||
Supports miniz_oxide and multiple zlib implementations. Supports zlib, gzip,
|
||||
and raw deflate streams.
|
||||
"""
|
||||
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 OR Apache-2.0"
|
||||
repository = "https://github.com/rust-lang/flate2-rs"
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
all-features = true
|
||||
rustdoc-args = [
|
||||
"--cfg",
|
||||
"docsrs",
|
||||
]
|
||||
|
||||
[dependencies.cloudflare-zlib-sys]
|
||||
version = "0.3.0"
|
||||
optional = true
|
||||
|
||||
[dependencies.crc32fast]
|
||||
version = "1.2.0"
|
||||
|
||||
[dependencies.libz-ng-sys]
|
||||
version = "1.1.8"
|
||||
optional = true
|
||||
|
||||
[dependencies.libz-sys]
|
||||
version = "1.1.8"
|
||||
optional = true
|
||||
default-features = false
|
||||
|
||||
[dependencies.miniz_oxide]
|
||||
version = "0.7.1"
|
||||
features = ["with-alloc"]
|
||||
optional = true
|
||||
default-features = false
|
||||
|
||||
[dev-dependencies.quickcheck]
|
||||
version = "1.0"
|
||||
default-features = false
|
||||
|
||||
[dev-dependencies.rand]
|
||||
version = "0.8"
|
||||
|
||||
[features]
|
||||
any_impl = []
|
||||
any_zlib = ["any_impl"]
|
||||
cloudflare_zlib = [
|
||||
"any_zlib",
|
||||
"cloudflare-zlib-sys",
|
||||
]
|
||||
default = ["rust_backend"]
|
||||
miniz-sys = ["rust_backend"]
|
||||
rust_backend = [
|
||||
"miniz_oxide",
|
||||
"any_impl",
|
||||
]
|
||||
zlib = [
|
||||
"any_zlib",
|
||||
"libz-sys",
|
||||
]
|
||||
zlib-default = [
|
||||
"any_zlib",
|
||||
"libz-sys/default",
|
||||
]
|
||||
zlib-ng = [
|
||||
"any_zlib",
|
||||
"libz-ng-sys",
|
||||
]
|
||||
zlib-ng-compat = [
|
||||
"zlib",
|
||||
"libz-sys/zlib-ng",
|
||||
]
|
||||
|
||||
[target."cfg(all(target_arch = \"wasm32\", not(target_os = \"emscripten\")))".dependencies.miniz_oxide]
|
||||
version = "0.7.1"
|
||||
features = ["with-alloc"]
|
||||
default-features = false
|
201
vendor/flate2/LICENSE-APACHE
vendored
Normal file
201
vendor/flate2/LICENSE-APACHE
vendored
Normal file
@ -0,0 +1,201 @@
|
||||
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.
|
25
vendor/flate2/LICENSE-MIT
vendored
Normal file
25
vendor/flate2/LICENSE-MIT
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
Copyright (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.
|
21
vendor/flate2/MAINTENANCE.md
vendored
Normal file
21
vendor/flate2/MAINTENANCE.md
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
This document explains how to perform the project's maintenance tasks.
|
||||
|
||||
### Creating a new release
|
||||
|
||||
#### Artifacts
|
||||
|
||||
* a tag of the version number
|
||||
* a new [crate version](https://crates.io/crates/flate2/versions)
|
||||
|
||||
#### Process
|
||||
|
||||
To generate all the artifacts above, one proceeds as follows:
|
||||
|
||||
1. `git checkout -b release-<next-version>` - move to a branch to prepare making changes to the repository. *Changes cannot be made to `main` as it is protected.*
|
||||
2. Edit `Cargo.toml` to the next package version.
|
||||
3. `gh pr create` to create a new PR for the current branch and **get it merged**.
|
||||
4. `cargo publish` to create a new release on `crates.io`.
|
||||
5. `git tag <next-version>` to remember the commit.
|
||||
6. `git push --tags` to push the new tag.
|
||||
7. Go to the newly created release page on GitHub and edit it by pressing the "Generate Release Notes" and the `@` button. Save the release.
|
||||
|
120
vendor/flate2/README.md
vendored
Normal file
120
vendor/flate2/README.md
vendored
Normal file
@ -0,0 +1,120 @@
|
||||
# flate2
|
||||
|
||||
[](https://crates.io/crates/flate2)
|
||||
[](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"
|
||||
```
|
||||
|
||||
## MSRV (Minimum Supported Rust Version) Policy
|
||||
|
||||
This crate supports the current stable and the last stable for the latest version.
|
||||
For example, if the current stable is 1.64, this crate supports 1.64 and 1.63.
|
||||
Older stables may work, but we don't guarantee these will continue to work.
|
||||
|
||||
## 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. If you
|
||||
want maximum performance, you can use the zlib-ng C library:
|
||||
|
||||
```toml
|
||||
[dependencies]
|
||||
flate2 = { version = "1.0.17", features = ["zlib-ng"], default-features = false }
|
||||
```
|
||||
|
||||
Note that the `"zlib-ng"` feature works even if some other part of your crate
|
||||
graph depends on zlib.
|
||||
|
||||
However, if you're already using another C or Rust library that depends on
|
||||
zlib, and you want to avoid including both zlib and zlib-ng, you can use that
|
||||
for Rust code as well:
|
||||
|
||||
```toml
|
||||
[dependencies]
|
||||
flate2 = { version = "1.0.17", features = ["zlib"], default-features = false }
|
||||
```
|
||||
|
||||
Or, if you have C or Rust code that depends on zlib and you want to use zlib-ng
|
||||
via libz-sys in zlib-compat mode, use:
|
||||
|
||||
```toml
|
||||
[dependencies]
|
||||
flate2 = { version = "1.0.17", features = ["zlib-ng-compat"], default-features = false }
|
||||
```
|
||||
|
||||
Note that when using the `"zlib-ng-compat"` feature, 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.
|
||||
To avoid that, use the `"zlib-ng"` feature instead.
|
||||
|
||||
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 an 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.
|
||||
|
||||
# License
|
||||
|
||||
This project is licensed under either of
|
||||
|
||||
* Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or
|
||||
https://www.apache.org/licenses/LICENSE-2.0)
|
||||
* MIT license ([LICENSE-MIT](LICENSE-MIT) or
|
||||
https://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.
|
26
vendor/flate2/examples/compress_file.rs
vendored
Normal file
26
vendor/flate2/examples/compress_file.rs
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
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());
|
||||
}
|
23
vendor/flate2/examples/decompress_file.rs
vendored
Normal file
23
vendor/flate2/examples/decompress_file.rs
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
use flate2::bufread;
|
||||
use std::env::args;
|
||||
use std::fs::File;
|
||||
use std::io::copy;
|
||||
use std::io::BufReader;
|
||||
use std::time::Instant;
|
||||
|
||||
fn main() {
|
||||
// E.g. `cargo run --example decompress_file examples/hello_world.txt.gz hello_world.txt`
|
||||
if args().len() != 3 {
|
||||
eprintln!("Usage: ./decompress_file `source` `target`");
|
||||
return;
|
||||
}
|
||||
let input = BufReader::new(File::open(args().nth(1).unwrap()).unwrap());
|
||||
let mut output = File::create(args().nth(2).unwrap()).unwrap();
|
||||
let source_len = input.get_ref().metadata().unwrap().len();
|
||||
let start = Instant::now();
|
||||
let mut decoder = bufread::GzDecoder::new(input);
|
||||
copy(&mut decoder, &mut output).unwrap();
|
||||
println!("Source len: {:?}", source_len);
|
||||
println!("Target len: {:?}", output.metadata().unwrap().len());
|
||||
println!("Elapsed: {:?}", start.elapsed());
|
||||
}
|
22
vendor/flate2/examples/deflatedecoder-bufread.rs
vendored
Normal file
22
vendor/flate2/examples/deflatedecoder-bufread.rs
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
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<u8>) -> io::Result<String> {
|
||||
let mut deflater = DeflateDecoder::new(&bytes[..]);
|
||||
let mut s = String::new();
|
||||
deflater.read_to_string(&mut s)?;
|
||||
Ok(s)
|
||||
}
|
22
vendor/flate2/examples/deflatedecoder-read.rs
vendored
Normal file
22
vendor/flate2/examples/deflatedecoder-read.rs
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
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<u8>) -> io::Result<String> {
|
||||
let mut deflater = DeflateDecoder::new(&bytes[..]);
|
||||
let mut s = String::new();
|
||||
deflater.read_to_string(&mut s)?;
|
||||
Ok(s)
|
||||
}
|
24
vendor/flate2/examples/deflatedecoder-write.rs
vendored
Normal file
24
vendor/flate2/examples/deflatedecoder-write.rs
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
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<u8> implements Write
|
||||
fn decode_reader(bytes: Vec<u8>) -> io::Result<String> {
|
||||
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)
|
||||
}
|
22
vendor/flate2/examples/deflateencoder-bufread.rs
vendored
Normal file
22
vendor/flate2/examples/deflateencoder-bufread.rs
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
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<Vec<u8>> {
|
||||
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)
|
||||
}
|
18
vendor/flate2/examples/deflateencoder-read.rs
vendored
Normal file
18
vendor/flate2/examples/deflateencoder-read.rs
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
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 Deflate compressed version of hello world
|
||||
fn deflateencoder_read_hello_world() -> io::Result<Vec<u8>> {
|
||||
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)
|
||||
}
|
10
vendor/flate2/examples/deflateencoder-write.rs
vendored
Normal file
10
vendor/flate2/examples/deflateencoder-write.rs
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
use flate2::write::DeflateEncoder;
|
||||
use flate2::Compression;
|
||||
use std::io::prelude::*;
|
||||
|
||||
// Vec<u8> 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());
|
||||
}
|
22
vendor/flate2/examples/gzbuilder.rs
vendored
Normal file
22
vendor/flate2/examples/gzbuilder.rs
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
use flate2::Compression;
|
||||
use flate2::GzBuilder;
|
||||
use std::fs::File;
|
||||
use std::io;
|
||||
use std::io::prelude::*;
|
||||
|
||||
// Compresses content of a text file into a gzip file
|
||||
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.txt.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(())
|
||||
}
|
21
vendor/flate2/examples/gzdecoder-bufread.rs
vendored
Normal file
21
vendor/flate2/examples/gzdecoder-bufread.rs
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
use flate2::write::GzEncoder;
|
||||
use flate2::{bufread, 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<u8>) -> io::Result<String> {
|
||||
let mut gz = bufread::GzDecoder::new(&bytes[..]);
|
||||
let mut s = String::new();
|
||||
gz.read_to_string(&mut s)?;
|
||||
Ok(s)
|
||||
}
|
21
vendor/flate2/examples/gzdecoder-read.rs
vendored
Normal file
21
vendor/flate2/examples/gzdecoder-read.rs
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
use flate2::write::GzEncoder;
|
||||
use flate2::{read, 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<u8>) -> io::Result<String> {
|
||||
let mut gz = read::GzDecoder::new(&bytes[..]);
|
||||
let mut s = String::new();
|
||||
gz.read_to_string(&mut s)?;
|
||||
Ok(s)
|
||||
}
|
24
vendor/flate2/examples/gzdecoder-write.rs
vendored
Normal file
24
vendor/flate2/examples/gzdecoder-write.rs
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
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<u8>) -> io::Result<String> {
|
||||
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)
|
||||
}
|
22
vendor/flate2/examples/gzencoder-bufread.rs
vendored
Normal file
22
vendor/flate2/examples/gzencoder-bufread.rs
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
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<Vec<u8>> {
|
||||
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)
|
||||
}
|
18
vendor/flate2/examples/gzencoder-read.rs
vendored
Normal file
18
vendor/flate2/examples/gzencoder-read.rs
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
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<Vec<u8>> {
|
||||
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)
|
||||
}
|
10
vendor/flate2/examples/gzencoder-write.rs
vendored
Normal file
10
vendor/flate2/examples/gzencoder-write.rs
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
use flate2::write::GzEncoder;
|
||||
use flate2::Compression;
|
||||
use std::io::prelude::*;
|
||||
|
||||
// Vec<u8> 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());
|
||||
}
|
22
vendor/flate2/examples/gzmultidecoder-bufread.rs
vendored
Normal file
22
vendor/flate2/examples/gzmultidecoder-bufread.rs
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
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<u8>) -> io::Result<String> {
|
||||
let mut gz = MultiGzDecoder::new(&bytes[..]);
|
||||
let mut s = String::new();
|
||||
gz.read_to_string(&mut s)?;
|
||||
Ok(s)
|
||||
}
|
22
vendor/flate2/examples/gzmultidecoder-read.rs
vendored
Normal file
22
vendor/flate2/examples/gzmultidecoder-read.rs
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
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<u8>) -> io::Result<String> {
|
||||
let mut gz = MultiGzDecoder::new(&bytes[..]);
|
||||
let mut s = String::new();
|
||||
gz.read_to_string(&mut s)?;
|
||||
Ok(s)
|
||||
}
|
1
vendor/flate2/examples/hello_world.txt
vendored
Normal file
1
vendor/flate2/examples/hello_world.txt
vendored
Normal file
@ -0,0 +1 @@
|
||||
Hello World
|
BIN
vendor/flate2/examples/hello_world.txt.gz
vendored
Normal file
BIN
vendor/flate2/examples/hello_world.txt.gz
vendored
Normal file
Binary file not shown.
22
vendor/flate2/examples/zlibdecoder-bufread.rs
vendored
Normal file
22
vendor/flate2/examples/zlibdecoder-bufread.rs
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
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<u8>) -> io::Result<String> {
|
||||
let mut z = ZlibDecoder::new(&bytes[..]);
|
||||
let mut s = String::new();
|
||||
z.read_to_string(&mut s)?;
|
||||
Ok(s)
|
||||
}
|
22
vendor/flate2/examples/zlibdecoder-read.rs
vendored
Normal file
22
vendor/flate2/examples/zlibdecoder-read.rs
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
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<u8>) -> io::Result<String> {
|
||||
let mut z = ZlibDecoder::new(&bytes[..]);
|
||||
let mut s = String::new();
|
||||
z.read_to_string(&mut s)?;
|
||||
Ok(s)
|
||||
}
|
24
vendor/flate2/examples/zlibdecoder-write.rs
vendored
Normal file
24
vendor/flate2/examples/zlibdecoder-write.rs
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
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<u8> implements Write
|
||||
fn decode_reader(bytes: Vec<u8>) -> io::Result<String> {
|
||||
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)
|
||||
}
|
22
vendor/flate2/examples/zlibencoder-bufread.rs
vendored
Normal file
22
vendor/flate2/examples/zlibencoder-bufread.rs
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
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<Vec<u8>> {
|
||||
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)
|
||||
}
|
19
vendor/flate2/examples/zlibencoder-read.rs
vendored
Normal file
19
vendor/flate2/examples/zlibencoder-read.rs
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
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<Vec<u8>> {
|
||||
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)
|
||||
}
|
10
vendor/flate2/examples/zlibencoder-write.rs
vendored
Normal file
10
vendor/flate2/examples/zlibencoder-write.rs
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
use flate2::write::ZlibEncoder;
|
||||
use flate2::Compression;
|
||||
use std::io::prelude::*;
|
||||
|
||||
// Vec<u8> 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());
|
||||
}
|
104
vendor/flate2/src/bufreader.rs
vendored
Normal file
104
vendor/flate2/src/bufreader.rs
vendored
Normal file
@ -0,0 +1,104 @@
|
||||
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// <https://github.com/rust-lang/rust/blob/HEAD/COPYRIGHT>.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, 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<R> {
|
||||
inner: R,
|
||||
buf: Box<[u8]>,
|
||||
pos: usize,
|
||||
cap: usize,
|
||||
}
|
||||
|
||||
impl<R> ::std::fmt::Debug for BufReader<R>
|
||||
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<R: Read> BufReader<R> {
|
||||
pub fn new(inner: R) -> BufReader<R> {
|
||||
BufReader::with_buf(vec![0; 32 * 1024], inner)
|
||||
}
|
||||
|
||||
pub fn with_buf(buf: Vec<u8>, inner: R) -> BufReader<R> {
|
||||
BufReader {
|
||||
inner,
|
||||
buf: buf.into_boxed_slice(),
|
||||
pos: 0,
|
||||
cap: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<R> BufReader<R> {
|
||||
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<R: Read> Read for BufReader<R> {
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
// 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<R: Read> BufRead for BufReader<R> {
|
||||
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);
|
||||
}
|
||||
}
|
184
vendor/flate2/src/crc.rs
vendored
Normal file
184
vendor/flate2/src/crc.rs
vendored
Normal file
@ -0,0 +1,184 @@
|
||||
//! 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<R> {
|
||||
inner: R,
|
||||
crc: Crc,
|
||||
}
|
||||
|
||||
impl Default for Crc {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
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 2<sup>32</sup>.
|
||||
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 = self.amt.wrapping_add(additional_crc.amt);
|
||||
self.hasher.combine(&additional_crc.hasher);
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: Read> CrcReader<R> {
|
||||
/// Create a new `CrcReader`.
|
||||
pub fn new(r: R) -> CrcReader<R> {
|
||||
CrcReader {
|
||||
inner: r,
|
||||
crc: Crc::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<R> CrcReader<R> {
|
||||
/// 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<R: Read> Read for CrcReader<R> {
|
||||
fn read(&mut self, into: &mut [u8]) -> io::Result<usize> {
|
||||
let amt = self.inner.read(into)?;
|
||||
self.crc.update(&into[..amt]);
|
||||
Ok(amt)
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: BufRead> BufRead for CrcReader<R> {
|
||||
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<W> {
|
||||
inner: W,
|
||||
crc: Crc,
|
||||
}
|
||||
|
||||
impl<W> CrcWriter<W> {
|
||||
/// 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<W: Write> CrcWriter<W> {
|
||||
/// Create a new `CrcWriter`.
|
||||
pub fn new(w: W) -> CrcWriter<W> {
|
||||
CrcWriter {
|
||||
inner: w,
|
||||
crc: Crc::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<W: Write> Write for CrcWriter<W> {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
let amt = self.inner.write(buf)?;
|
||||
self.crc.update(&buf[..amt]);
|
||||
Ok(amt)
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
self.inner.flush()
|
||||
}
|
||||
}
|
245
vendor/flate2/src/deflate/bufread.rs
vendored
Normal file
245
vendor/flate2/src/deflate/bufread.rs
vendored
Normal file
@ -0,0 +1,245 @@
|
||||
use std::io;
|
||||
use std::io::prelude::*;
|
||||
use std::mem;
|
||||
|
||||
use crate::zio;
|
||||
use crate::{Compress, Decompress};
|
||||
|
||||
/// A DEFLATE encoder, or compressor.
|
||||
///
|
||||
/// This structure implements a [`Read`] interface. When read from, it reads
|
||||
/// uncompressed data from the underlying [`BufRead`] and provides the compressed data.
|
||||
///
|
||||
/// [`Read`]: https://doc.rust-lang.org/std/io/trait.Read.html
|
||||
/// [`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<Vec<u8>> {
|
||||
/// 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<R> {
|
||||
obj: R,
|
||||
data: Compress,
|
||||
}
|
||||
|
||||
impl<R: BufRead> DeflateEncoder<R> {
|
||||
/// 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<R> {
|
||||
DeflateEncoder {
|
||||
obj: r,
|
||||
data: Compress::new(level, false),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn reset_encoder_data<R>(zlib: &mut DeflateEncoder<R>) {
|
||||
zlib.data.reset();
|
||||
}
|
||||
|
||||
impl<R> DeflateEncoder<R> {
|
||||
/// 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<R: BufRead> Read for DeflateEncoder<R> {
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
zio::read(&mut self.obj, &mut self.data, buf)
|
||||
}
|
||||
}
|
||||
|
||||
impl<W: BufRead + Write> Write for DeflateEncoder<W> {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
self.get_mut().write(buf)
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
self.get_mut().flush()
|
||||
}
|
||||
}
|
||||
|
||||
/// A DEFLATE decoder, or decompressor.
|
||||
///
|
||||
/// This structure implements a [`Read`] interface. When read from, it reads
|
||||
/// compressed data from the underlying [`BufRead`] and provides the uncompressed data.
|
||||
///
|
||||
/// [`Read`]: https://doc.rust-lang.org/std/io/trait.Read.html
|
||||
/// [`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<u8>) -> io::Result<String> {
|
||||
/// let mut deflater = DeflateDecoder::new(&bytes[..]);
|
||||
/// let mut s = String::new();
|
||||
/// deflater.read_to_string(&mut s)?;
|
||||
/// Ok(s)
|
||||
/// }
|
||||
/// ```
|
||||
#[derive(Debug)]
|
||||
pub struct DeflateDecoder<R> {
|
||||
obj: R,
|
||||
data: Decompress,
|
||||
}
|
||||
|
||||
pub fn reset_decoder_data<R>(zlib: &mut DeflateDecoder<R>) {
|
||||
zlib.data = Decompress::new(false);
|
||||
}
|
||||
|
||||
impl<R: BufRead> DeflateDecoder<R> {
|
||||
/// Creates a new decoder which will decompress data read from the given
|
||||
/// stream.
|
||||
pub fn new(r: R) -> DeflateDecoder<R> {
|
||||
DeflateDecoder {
|
||||
obj: r,
|
||||
data: Decompress::new(false),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<R> DeflateDecoder<R> {
|
||||
/// 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 decoder 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<R: BufRead> Read for DeflateDecoder<R> {
|
||||
fn read(&mut self, into: &mut [u8]) -> io::Result<usize> {
|
||||
zio::read(&mut self.obj, &mut self.data, into)
|
||||
}
|
||||
}
|
||||
|
||||
impl<W: BufRead + Write> Write for DeflateDecoder<W> {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
self.get_mut().write(buf)
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
self.get_mut().flush()
|
||||
}
|
||||
}
|
193
vendor/flate2/src/deflate/mod.rs
vendored
Normal file
193
vendor/flate2/src/deflate/mod.rs
vendored
Normal file
@ -0,0 +1,193 @@
|
||||
pub 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::<Vec<_>>();
|
||||
for _ in 0..200 {
|
||||
let to_write = &v[..thread_rng().gen_range(0..v.len())];
|
||||
real.extend(to_write.iter().copied());
|
||||
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_eq!(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_eq!(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::<Vec<_>>();
|
||||
for _ in 0..200 {
|
||||
let to_write = &v[..thread_rng().gen_range(0..v.len())];
|
||||
real.extend(to_write.iter().copied());
|
||||
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().copied());
|
||||
}
|
||||
|
||||
let mut r = read::DeflateDecoder::new(&result[..]);
|
||||
let mut ret = Vec::new();
|
||||
r.read_to_end(&mut ret).unwrap();
|
||||
assert_eq!(ret, real);
|
||||
assert_eq!(r.total_in(), result_len as u64);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn roundtrip2() {
|
||||
let v = crate::random_bytes().take(1024 * 1024).collect::<Vec<_>>();
|
||||
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::<Vec<_>>();
|
||||
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_eq!(w, v);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn reset_writer() {
|
||||
let v = crate::random_bytes().take(1024 * 1024).collect::<Vec<_>>();
|
||||
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::<Vec<_>>();
|
||||
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::<Vec<_>>();
|
||||
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_eq!(d.read(&mut data).unwrap(), 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn qc_reader() {
|
||||
::quickcheck::quickcheck(test as fn(_) -> _);
|
||||
|
||||
fn test(v: Vec<u8>) -> 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<u8>) -> 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()
|
||||
}
|
||||
}
|
||||
}
|
241
vendor/flate2/src/deflate/read.rs
vendored
Normal file
241
vendor/flate2/src/deflate/read.rs
vendored
Normal file
@ -0,0 +1,241 @@
|
||||
use std::io;
|
||||
use std::io::prelude::*;
|
||||
|
||||
use super::bufread;
|
||||
use crate::bufreader::BufReader;
|
||||
|
||||
/// A DEFLATE encoder, or compressor.
|
||||
///
|
||||
/// This structure implements a [`Read`] interface. When read from, it reads
|
||||
/// uncompressed data from the underlying [`Read`] and provides the 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<Vec<u8>> {
|
||||
/// let mut ret_vec = Vec::new();
|
||||
/// let c = b"hello world";
|
||||
/// let mut deflater = DeflateEncoder::new(&c[..], Compression::fast());
|
||||
/// deflater.read_to_end(&mut ret_vec)?;
|
||||
/// Ok(ret_vec)
|
||||
/// }
|
||||
/// ```
|
||||
#[derive(Debug)]
|
||||
pub struct DeflateEncoder<R> {
|
||||
inner: bufread::DeflateEncoder<BufReader<R>>,
|
||||
}
|
||||
|
||||
impl<R: Read> DeflateEncoder<R> {
|
||||
/// 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<R> {
|
||||
DeflateEncoder {
|
||||
inner: bufread::DeflateEncoder::new(BufReader::new(r), level),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<R> DeflateEncoder<R> {
|
||||
/// 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<R: Read> Read for DeflateEncoder<R> {
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
self.inner.read(buf)
|
||||
}
|
||||
}
|
||||
|
||||
impl<W: Read + Write> Write for DeflateEncoder<W> {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
self.get_mut().write(buf)
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
self.get_mut().flush()
|
||||
}
|
||||
}
|
||||
|
||||
/// A DEFLATE decoder, or decompressor.
|
||||
///
|
||||
/// This structure implements a [`Read`] interface. When read from, it reads
|
||||
/// compressed data from the underlying [`Read`] and provides the 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::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<u8>) -> io::Result<String> {
|
||||
/// let mut deflater = DeflateDecoder::new(&bytes[..]);
|
||||
/// let mut s = String::new();
|
||||
/// deflater.read_to_string(&mut s)?;
|
||||
/// Ok(s)
|
||||
/// }
|
||||
/// ```
|
||||
#[derive(Debug)]
|
||||
pub struct DeflateDecoder<R> {
|
||||
inner: bufread::DeflateDecoder<BufReader<R>>,
|
||||
}
|
||||
|
||||
impl<R: Read> DeflateDecoder<R> {
|
||||
/// Creates a new decoder which will decompress data read from the given
|
||||
/// stream.
|
||||
pub fn new(r: R) -> DeflateDecoder<R> {
|
||||
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<u8>) -> DeflateDecoder<R> {
|
||||
DeflateDecoder {
|
||||
inner: bufread::DeflateDecoder::new(BufReader::with_buf(buf, r)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<R> DeflateDecoder<R> {
|
||||
/// 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 decoder 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<R: Read> Read for DeflateDecoder<R> {
|
||||
fn read(&mut self, into: &mut [u8]) -> io::Result<usize> {
|
||||
self.inner.read(into)
|
||||
}
|
||||
}
|
||||
|
||||
impl<W: Read + Write> Write for DeflateDecoder<W> {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
self.get_mut().write(buf)
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
self.get_mut().flush()
|
||||
}
|
||||
}
|
322
vendor/flate2/src/deflate/write.rs
vendored
Normal file
322
vendor/flate2/src/deflate/write.rs
vendored
Normal file
@ -0,0 +1,322 @@
|
||||
use std::io;
|
||||
use std::io::prelude::*;
|
||||
|
||||
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<u8> 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<W: Write> {
|
||||
inner: zio::Writer<W, Compress>,
|
||||
}
|
||||
|
||||
impl<W: Write> DeflateEncoder<W> {
|
||||
/// 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<W> {
|
||||
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<W> {
|
||||
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<W> {
|
||||
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<W> {
|
||||
self.inner.flush()?;
|
||||
Ok(self.inner.take_inner())
|
||||
}
|
||||
|
||||
/// Returns the number of bytes that have been written to this compressor.
|
||||
///
|
||||
/// 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<W: Write> Write for DeflateEncoder<W> {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
self.inner.write(buf)
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
self.inner.flush()
|
||||
}
|
||||
}
|
||||
|
||||
impl<W: Read + Write> Read for DeflateEncoder<W> {
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
self.inner.get_mut().read(buf)
|
||||
}
|
||||
}
|
||||
|
||||
/// 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<u8> implements Write
|
||||
/// fn decode_writer(bytes: Vec<u8>) -> io::Result<String> {
|
||||
/// 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<W: Write> {
|
||||
inner: zio::Writer<W, Decompress>,
|
||||
}
|
||||
|
||||
impl<W: Write> DeflateDecoder<W> {
|
||||
/// 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<W> {
|
||||
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<W> {
|
||||
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<W> {
|
||||
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<W: Write> Write for DeflateDecoder<W> {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
self.inner.write(buf)
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
self.inner.flush()
|
||||
}
|
||||
}
|
||||
|
||||
impl<W: Read + Write> Read for DeflateDecoder<W> {
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
self.inner.get_mut().read(buf)
|
||||
}
|
||||
}
|
433
vendor/flate2/src/ffi/c.rs
vendored
Normal file
433
vendor/flate2/src/ffi/c.rs
vendored
Normal file
@ -0,0 +1,433 @@
|
||||
//! 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::os::raw::{c_int, c_uint, c_void};
|
||||
use std::ptr;
|
||||
|
||||
use super::*;
|
||||
use crate::mem::{self, FlushDecompress, Status};
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct ErrorMessage(Option<&'static str>);
|
||||
|
||||
impl ErrorMessage {
|
||||
pub fn get(&self) -> Option<&str> {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
pub struct StreamWrapper {
|
||||
pub inner: Box<mz_stream>,
|
||||
}
|
||||
|
||||
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::<usize>();
|
||||
|
||||
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::<usize>()))
|
||||
{
|
||||
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 freed 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<D: Direction> Send for Stream<D> {}
|
||||
unsafe impl<D: Direction> Sync for Stream<D> {}
|
||||
|
||||
/// 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<D: Direction> {
|
||||
pub stream_wrapper: StreamWrapper,
|
||||
pub total_in: u64,
|
||||
pub total_out: u64,
|
||||
pub _marker: marker::PhantomData<D>,
|
||||
}
|
||||
|
||||
impl<D: Direction> Stream<D> {
|
||||
pub fn msg(&self) -> ErrorMessage {
|
||||
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()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Direction> Drop for Stream<D> {
|
||||
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<DirDecompress>,
|
||||
}
|
||||
|
||||
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<Status, DecompressError> {
|
||||
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 as usize) as c_uint;
|
||||
raw.next_out = output.as_mut_ptr();
|
||||
raw.avail_out = cmp::min(output.len(), c_uint::MAX 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;
|
||||
|
||||
// reset these pointers so we don't accidentally read them later
|
||||
raw.next_in = ptr::null_mut();
|
||||
raw.avail_in = 0;
|
||||
raw.next_out = ptr::null_mut();
|
||||
raw.avail_out = 0;
|
||||
|
||||
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),
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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<DirCompress>,
|
||||
}
|
||||
|
||||
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<Status, CompressError> {
|
||||
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 as usize) as c_uint;
|
||||
raw.next_out = output.as_mut_ptr();
|
||||
raw.avail_out = cmp::min(output.len(), c_uint::MAX 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;
|
||||
|
||||
// reset these pointers so we don't accidentally read them later
|
||||
raw.next_in = ptr::null_mut();
|
||||
raw.avail_in = 0;
|
||||
raw.next_out = ptr::null_mut();
|
||||
raw.avail_out = 0;
|
||||
|
||||
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::*;
|
||||
|
||||
/// For backwards compatibility, we provide symbols as `mz_` to mimic the miniz API
|
||||
#[allow(bad_style)]
|
||||
mod c_backend {
|
||||
use std::mem;
|
||||
use std::os::raw::{c_char, c_int};
|
||||
|
||||
#[cfg(feature = "zlib-ng")]
|
||||
use libz_ng_sys as libz;
|
||||
|
||||
#[cfg(all(not(feature = "zlib-ng"), feature = "cloudflare_zlib"))]
|
||||
use cloudflare_zlib_sys as libz;
|
||||
|
||||
#[cfg(all(not(feature = "cloudflare_zlib"), not(feature = "zlib-ng")))]
|
||||
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;
|
||||
|
||||
#[cfg(feature = "zlib-ng")]
|
||||
const ZLIB_VERSION: &'static str = "2.1.0.devel\0";
|
||||
#[cfg(not(feature = "zlib-ng"))]
|
||||
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::<mz_stream>() 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::<mz_stream>() as c_int,
|
||||
)
|
||||
}
|
||||
}
|
52
vendor/flate2/src/ffi/mod.rs
vendored
Normal file
52
vendor/flate2/src/ffi/mod.rs
vendored
Normal file
@ -0,0 +1,52 @@
|
||||
//! 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<Status, DecompressError>;
|
||||
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<Status, CompressError>;
|
||||
fn reset(&mut self);
|
||||
}
|
||||
|
||||
// Default to Rust implementation unless explicitly opted in to a different backend.
|
||||
#[cfg(feature = "any_zlib")]
|
||||
mod c;
|
||||
#[cfg(feature = "any_zlib")]
|
||||
pub use self::c::*;
|
||||
|
||||
#[cfg(all(not(feature = "any_zlib"), feature = "miniz_oxide"))]
|
||||
mod rust;
|
||||
#[cfg(all(not(feature = "any_zlib"), feature = "miniz_oxide"))]
|
||||
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)
|
||||
}
|
||||
}
|
183
vendor/flate2/src/ffi/rust.rs
vendored
Normal file
183
vendor/flate2/src/ffi/rust.rs
vendored
Normal file
@ -0,0 +1,183 @@
|
||||
//! 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<InflateState>,
|
||||
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<Status, DecompressError> {
|
||||
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<CompressorOxide>,
|
||||
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<CompressorOxide> = 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<Status, CompressError> {
|
||||
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
|
||||
}
|
||||
}
|
483
vendor/flate2/src/gz/bufread.rs
vendored
Normal file
483
vendor/flate2/src/gz/bufread.rs
vendored
Normal file
@ -0,0 +1,483 @@
|
||||
use std::cmp;
|
||||
use std::io;
|
||||
use std::io::prelude::*;
|
||||
use std::mem;
|
||||
|
||||
use super::{corrupt, read_into, GzBuilder, GzHeader, GzHeaderParser};
|
||||
use crate::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;
|
||||
min
|
||||
}
|
||||
|
||||
/// A gzip streaming encoder
|
||||
///
|
||||
/// This structure implements a [`Read`] interface. When read from, it reads
|
||||
/// uncompressed data from the underlying [`BufRead`] and provides the compressed data.
|
||||
///
|
||||
/// [`Read`]: https://doc.rust-lang.org/std/io/trait.Read.html
|
||||
/// [`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<Vec<u8>> {
|
||||
/// 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<R> {
|
||||
inner: deflate::bufread::DeflateEncoder<CrcReader<R>>,
|
||||
header: Vec<u8>,
|
||||
pos: usize,
|
||||
eof: bool,
|
||||
}
|
||||
|
||||
pub fn gz_encoder<R: BufRead>(header: Vec<u8>, r: R, lvl: Compression) -> GzEncoder<R> {
|
||||
let crc = CrcReader::new(r);
|
||||
GzEncoder {
|
||||
inner: deflate::bufread::DeflateEncoder::new(crc, lvl),
|
||||
header,
|
||||
pos: 0,
|
||||
eof: false,
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: BufRead> GzEncoder<R> {
|
||||
/// 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<R> {
|
||||
GzBuilder::new().buf_read(r, level)
|
||||
}
|
||||
|
||||
fn read_footer(&mut self, into: &mut [u8]) -> io::Result<usize> {
|
||||
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<R> GzEncoder<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 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<R: BufRead> Read for GzEncoder<R> {
|
||||
fn read(&mut self, mut into: &mut [u8]) -> io::Result<usize> {
|
||||
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<R: BufRead + Write> Write for GzEncoder<R> {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
self.get_mut().write(buf)
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
self.get_mut().flush()
|
||||
}
|
||||
}
|
||||
|
||||
/// A decoder for a single member of a [gzip file].
|
||||
///
|
||||
/// This structure implements a [`Read`] interface. When read from, it reads
|
||||
/// compressed data from the underlying [`BufRead`] and provides the uncompressed data.
|
||||
///
|
||||
/// After reading a single member of the gzip data this reader will return
|
||||
/// Ok(0) even if there are more bytes available in the underlying reader.
|
||||
/// If you need the following bytes, call `into_inner()` after Ok(0) to
|
||||
/// recover the underlying reader.
|
||||
///
|
||||
/// To handle gzip files that may have multiple members, see [`MultiGzDecoder`]
|
||||
/// or read more
|
||||
/// [in the introduction](../index.html#about-multi-member-gzip-files).
|
||||
///
|
||||
/// [gzip file]: https://www.rfc-editor.org/rfc/rfc1952#page-5
|
||||
/// [`Read`]: https://doc.rust-lang.org/std/io/trait.Read.html
|
||||
/// [`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<u8>) -> io::Result<String> {
|
||||
/// let mut gz = GzDecoder::new(&bytes[..]);
|
||||
/// let mut s = String::new();
|
||||
/// gz.read_to_string(&mut s)?;
|
||||
/// Ok(s)
|
||||
/// }
|
||||
/// ```
|
||||
#[derive(Debug)]
|
||||
pub struct GzDecoder<R> {
|
||||
state: GzState,
|
||||
reader: CrcReader<deflate::bufread::DeflateDecoder<R>>,
|
||||
multi: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
enum GzState {
|
||||
Header(GzHeaderParser),
|
||||
Body(GzHeader),
|
||||
Finished(GzHeader, usize, [u8; 8]),
|
||||
Err(io::Error),
|
||||
End(Option<GzHeader>),
|
||||
}
|
||||
|
||||
impl<R: BufRead> GzDecoder<R> {
|
||||
/// Creates a new decoder from the given reader, immediately parsing the
|
||||
/// gzip header.
|
||||
pub fn new(mut r: R) -> GzDecoder<R> {
|
||||
let mut header_parser = GzHeaderParser::new();
|
||||
|
||||
let state = match header_parser.parse(&mut r) {
|
||||
Ok(_) => GzState::Body(GzHeader::from(header_parser)),
|
||||
Err(ref err) if io::ErrorKind::WouldBlock == err.kind() => {
|
||||
GzState::Header(header_parser)
|
||||
}
|
||||
Err(err) => GzState::Err(err),
|
||||
};
|
||||
|
||||
GzDecoder {
|
||||
state,
|
||||
reader: CrcReader::new(deflate::bufread::DeflateDecoder::new(r)),
|
||||
multi: false,
|
||||
}
|
||||
}
|
||||
|
||||
fn multi(mut self, flag: bool) -> GzDecoder<R> {
|
||||
self.multi = flag;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<R> GzDecoder<R> {
|
||||
/// Returns the header associated with this stream, if it was valid
|
||||
pub fn header(&self) -> Option<&GzHeader> {
|
||||
match &self.state {
|
||||
GzState::Body(header) | GzState::Finished(header, _, _) => Some(header),
|
||||
GzState::End(header) => header.as_ref(),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// 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 decoder 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<R: BufRead> Read for GzDecoder<R> {
|
||||
fn read(&mut self, into: &mut [u8]) -> io::Result<usize> {
|
||||
loop {
|
||||
match &mut self.state {
|
||||
GzState::Header(parser) => {
|
||||
parser.parse(self.reader.get_mut().get_mut())?;
|
||||
self.state = GzState::Body(GzHeader::from(mem::take(parser)));
|
||||
}
|
||||
GzState::Body(header) => {
|
||||
if into.is_empty() {
|
||||
return Ok(0);
|
||||
}
|
||||
match self.reader.read(into)? {
|
||||
0 => {
|
||||
self.state = GzState::Finished(mem::take(header), 0, [0; 8]);
|
||||
}
|
||||
n => {
|
||||
return Ok(n);
|
||||
}
|
||||
}
|
||||
}
|
||||
GzState::Finished(header, pos, buf) => {
|
||||
if *pos < buf.len() {
|
||||
*pos += read_into(self.reader.get_mut().get_mut(), &mut buf[*pos..])?;
|
||||
} else {
|
||||
let (crc, amt) = finish(&buf);
|
||||
|
||||
if crc != self.reader.crc().sum() || amt != self.reader.crc().amount() {
|
||||
self.state = GzState::End(Some(mem::take(header)));
|
||||
return Err(corrupt());
|
||||
} else if self.multi {
|
||||
let is_eof = self
|
||||
.reader
|
||||
.get_mut()
|
||||
.get_mut()
|
||||
.fill_buf()
|
||||
.map(|buf| buf.is_empty())?;
|
||||
|
||||
if is_eof {
|
||||
self.state = GzState::End(Some(mem::take(header)));
|
||||
} else {
|
||||
self.reader.reset();
|
||||
self.reader.get_mut().reset_data();
|
||||
self.state = GzState::Header(GzHeaderParser::new())
|
||||
}
|
||||
} else {
|
||||
self.state = GzState::End(Some(mem::take(header)));
|
||||
}
|
||||
}
|
||||
}
|
||||
GzState::Err(err) => {
|
||||
let result = Err(mem::replace(err, io::ErrorKind::Other.into()));
|
||||
self.state = GzState::End(None);
|
||||
return result;
|
||||
}
|
||||
GzState::End(_) => return Ok(0),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: BufRead + Write> Write for GzDecoder<R> {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
self.get_mut().write(buf)
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
self.get_mut().flush()
|
||||
}
|
||||
}
|
||||
|
||||
/// A gzip streaming decoder that decodes a [gzip file] that may have multiple members.
|
||||
///
|
||||
/// This structure implements a [`Read`] interface. When read from, it reads
|
||||
/// compressed data from the underlying [`BufRead`] and provides the uncompressed data.
|
||||
///
|
||||
/// A gzip file consists of a series of *members* concatenated one after another.
|
||||
/// MultiGzDecoder decodes all members from the data and only returns Ok(0) when the
|
||||
/// underlying reader does. For a file, this reads to the end of the file.
|
||||
///
|
||||
/// To handle members seperately, see [GzDecoder] or read more
|
||||
/// [in the introduction](../index.html#about-multi-member-gzip-files).
|
||||
///
|
||||
/// [gzip file]: https://www.rfc-editor.org/rfc/rfc1952#page-5
|
||||
/// [`Read`]: https://doc.rust-lang.org/std/io/trait.Read.html
|
||||
/// [`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<u8>) -> io::Result<String> {
|
||||
/// let mut gz = MultiGzDecoder::new(&bytes[..]);
|
||||
/// let mut s = String::new();
|
||||
/// gz.read_to_string(&mut s)?;
|
||||
/// Ok(s)
|
||||
/// }
|
||||
/// ```
|
||||
#[derive(Debug)]
|
||||
pub struct MultiGzDecoder<R>(GzDecoder<R>);
|
||||
|
||||
impl<R: BufRead> MultiGzDecoder<R> {
|
||||
/// 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<R> {
|
||||
MultiGzDecoder(GzDecoder::new(r).multi(true))
|
||||
}
|
||||
}
|
||||
|
||||
impl<R> MultiGzDecoder<R> {
|
||||
/// 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 decoder 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<R: BufRead> Read for MultiGzDecoder<R> {
|
||||
fn read(&mut self, into: &mut [u8]) -> io::Result<usize> {
|
||||
self.0.read(into)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use crate::bufread::GzDecoder;
|
||||
use crate::gz::write;
|
||||
use crate::Compression;
|
||||
use std::io::{Read, Write};
|
||||
|
||||
// GzDecoder consumes one gzip member and then returns 0 for subsequent reads, allowing any
|
||||
// additional data to be consumed by the caller.
|
||||
#[test]
|
||||
fn decode_extra_data() {
|
||||
let expected = "Hello World";
|
||||
|
||||
let compressed = {
|
||||
let mut e = write::GzEncoder::new(Vec::new(), Compression::default());
|
||||
e.write(expected.as_ref()).unwrap();
|
||||
let mut b = e.finish().unwrap();
|
||||
b.push(b'x');
|
||||
b
|
||||
};
|
||||
|
||||
let mut output = Vec::new();
|
||||
let mut decoder = GzDecoder::new(compressed.as_slice());
|
||||
let decoded_bytes = decoder.read_to_end(&mut output).unwrap();
|
||||
assert_eq!(decoded_bytes, output.len());
|
||||
let actual = std::str::from_utf8(&output).expect("String parsing error");
|
||||
assert_eq!(
|
||||
actual, expected,
|
||||
"after decompression we obtain the original input"
|
||||
);
|
||||
|
||||
output.clear();
|
||||
assert_eq!(
|
||||
decoder.read(&mut output).unwrap(),
|
||||
0,
|
||||
"subsequent read of decoder returns 0, but inner reader can return additional data"
|
||||
);
|
||||
let mut reader = decoder.into_inner();
|
||||
assert_eq!(
|
||||
reader.read_to_end(&mut output).unwrap(),
|
||||
1,
|
||||
"extra data is accessible in underlying buf-read"
|
||||
);
|
||||
assert_eq!(output, b"x");
|
||||
}
|
||||
}
|
644
vendor/flate2/src/gz/mod.rs
vendored
Normal file
644
vendor/flate2/src/gz/mod.rs
vendored
Normal file
@ -0,0 +1,644 @@
|
||||
use std::ffi::CString;
|
||||
use std::io::{BufRead, Error, ErrorKind, Read, Result, Write};
|
||||
use std::time;
|
||||
|
||||
use crate::bufreader::BufReader;
|
||||
use crate::{Compression, Crc};
|
||||
|
||||
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 static FRESERVED: u8 = 1 << 5 | 1 << 6 | 1 << 7;
|
||||
|
||||
pub mod bufread;
|
||||
pub mod read;
|
||||
pub mod write;
|
||||
|
||||
// The maximum length of the header filename and comment fields. More than
|
||||
// enough for these fields in reasonable use, but prevents possible attacks.
|
||||
const MAX_HEADER_BUF: usize = 65535;
|
||||
|
||||
/// 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<Vec<u8>>,
|
||||
filename: Option<Vec<u8>>,
|
||||
comment: Option<Vec<u8>>,
|
||||
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<time::SystemTime> {
|
||||
if self.mtime == 0 {
|
||||
None
|
||||
} else {
|
||||
let duration = time::Duration::new(u64::from(self.mtime), 0);
|
||||
let datetime = time::UNIX_EPOCH + duration;
|
||||
Some(datetime)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum GzHeaderState {
|
||||
Start(u8, [u8; 10]),
|
||||
Xlen(Option<Box<Crc>>, u8, [u8; 2]),
|
||||
Extra(Option<Box<Crc>>, u16),
|
||||
Filename(Option<Box<Crc>>),
|
||||
Comment(Option<Box<Crc>>),
|
||||
Crc(Option<Box<Crc>>, u8, [u8; 2]),
|
||||
Complete,
|
||||
}
|
||||
|
||||
impl Default for GzHeaderState {
|
||||
fn default() -> Self {
|
||||
Self::Complete
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct GzHeaderParser {
|
||||
state: GzHeaderState,
|
||||
flags: u8,
|
||||
header: GzHeader,
|
||||
}
|
||||
|
||||
impl GzHeaderParser {
|
||||
fn new() -> Self {
|
||||
GzHeaderParser {
|
||||
state: GzHeaderState::Start(0, [0; 10]),
|
||||
flags: 0,
|
||||
header: GzHeader::default(),
|
||||
}
|
||||
}
|
||||
|
||||
fn parse<'a, R: Read>(&mut self, r: &'a mut R) -> Result<()> {
|
||||
loop {
|
||||
match &mut self.state {
|
||||
GzHeaderState::Start(count, buffer) => {
|
||||
while (*count as usize) < buffer.len() {
|
||||
*count += read_into(r, &mut buffer[*count as usize..])? as u8;
|
||||
}
|
||||
// Gzip identification bytes
|
||||
if buffer[0] != 0x1f || buffer[1] != 0x8b {
|
||||
return Err(bad_header());
|
||||
}
|
||||
// Gzip compression method (8 = deflate)
|
||||
if buffer[2] != 8 {
|
||||
return Err(bad_header());
|
||||
}
|
||||
self.flags = buffer[3];
|
||||
// RFC1952: "must give an error indication if any reserved bit is non-zero"
|
||||
if self.flags & FRESERVED != 0 {
|
||||
return Err(bad_header());
|
||||
}
|
||||
self.header.mtime = ((buffer[4] as u32) << 0)
|
||||
| ((buffer[5] as u32) << 8)
|
||||
| ((buffer[6] as u32) << 16)
|
||||
| ((buffer[7] as u32) << 24);
|
||||
let _xfl = buffer[8];
|
||||
self.header.operating_system = buffer[9];
|
||||
let crc = if self.flags & FHCRC != 0 {
|
||||
let mut crc = Box::new(Crc::new());
|
||||
crc.update(buffer);
|
||||
Some(crc)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
self.state = GzHeaderState::Xlen(crc, 0, [0; 2]);
|
||||
}
|
||||
GzHeaderState::Xlen(crc, count, buffer) => {
|
||||
if self.flags & FEXTRA != 0 {
|
||||
while (*count as usize) < buffer.len() {
|
||||
*count += read_into(r, &mut buffer[*count as usize..])? as u8;
|
||||
}
|
||||
if let Some(crc) = crc {
|
||||
crc.update(buffer);
|
||||
}
|
||||
let xlen = parse_le_u16(&buffer);
|
||||
self.header.extra = Some(vec![0; xlen as usize]);
|
||||
self.state = GzHeaderState::Extra(crc.take(), 0);
|
||||
} else {
|
||||
self.state = GzHeaderState::Filename(crc.take());
|
||||
}
|
||||
}
|
||||
GzHeaderState::Extra(crc, count) => {
|
||||
debug_assert!(self.header.extra.is_some());
|
||||
let extra = self.header.extra.as_mut().unwrap();
|
||||
while (*count as usize) < extra.len() {
|
||||
*count += read_into(r, &mut extra[*count as usize..])? as u16;
|
||||
}
|
||||
if let Some(crc) = crc {
|
||||
crc.update(extra);
|
||||
}
|
||||
self.state = GzHeaderState::Filename(crc.take());
|
||||
}
|
||||
GzHeaderState::Filename(crc) => {
|
||||
if self.flags & FNAME != 0 {
|
||||
let filename = self.header.filename.get_or_insert_with(Vec::new);
|
||||
read_to_nul(r, filename)?;
|
||||
if let Some(crc) = crc {
|
||||
crc.update(filename);
|
||||
crc.update(b"\0");
|
||||
}
|
||||
}
|
||||
self.state = GzHeaderState::Comment(crc.take());
|
||||
}
|
||||
GzHeaderState::Comment(crc) => {
|
||||
if self.flags & FCOMMENT != 0 {
|
||||
let comment = self.header.comment.get_or_insert_with(Vec::new);
|
||||
read_to_nul(r, comment)?;
|
||||
if let Some(crc) = crc {
|
||||
crc.update(comment);
|
||||
crc.update(b"\0");
|
||||
}
|
||||
}
|
||||
self.state = GzHeaderState::Crc(crc.take(), 0, [0; 2]);
|
||||
}
|
||||
GzHeaderState::Crc(crc, count, buffer) => {
|
||||
if let Some(crc) = crc {
|
||||
debug_assert!(self.flags & FHCRC != 0);
|
||||
while (*count as usize) < buffer.len() {
|
||||
*count += read_into(r, &mut buffer[*count as usize..])? as u8;
|
||||
}
|
||||
let stored_crc = parse_le_u16(&buffer);
|
||||
let calced_crc = crc.sum() as u16;
|
||||
if stored_crc != calced_crc {
|
||||
return Err(corrupt());
|
||||
}
|
||||
}
|
||||
self.state = GzHeaderState::Complete;
|
||||
}
|
||||
GzHeaderState::Complete => {
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn header(&self) -> Option<&GzHeader> {
|
||||
match self.state {
|
||||
GzHeaderState::Complete => Some(&self.header),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<GzHeaderParser> for GzHeader {
|
||||
fn from(parser: GzHeaderParser) -> Self {
|
||||
debug_assert!(matches!(parser.state, GzHeaderState::Complete));
|
||||
parser.header
|
||||
}
|
||||
}
|
||||
|
||||
// Attempt to fill the `buffer` from `r`. Return the number of bytes read.
|
||||
// Return an error if EOF is read before the buffer is full. This differs
|
||||
// from `read` in that Ok(0) means that more data may be available.
|
||||
fn read_into<R: Read>(r: &mut R, buffer: &mut [u8]) -> Result<usize> {
|
||||
debug_assert!(!buffer.is_empty());
|
||||
match r.read(buffer) {
|
||||
Ok(0) => Err(ErrorKind::UnexpectedEof.into()),
|
||||
Ok(n) => Ok(n),
|
||||
Err(ref e) if e.kind() == ErrorKind::Interrupted => Ok(0),
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
}
|
||||
|
||||
// Read `r` up to the first nul byte, pushing non-nul bytes to `buffer`.
|
||||
fn read_to_nul<R: Read>(r: &mut R, buffer: &mut Vec<u8>) -> Result<()> {
|
||||
let mut bytes = r.bytes();
|
||||
loop {
|
||||
match bytes.next().transpose()? {
|
||||
Some(byte) if byte == 0 => {
|
||||
return Ok(());
|
||||
}
|
||||
Some(_) if buffer.len() == MAX_HEADER_BUF => {
|
||||
return Err(Error::new(
|
||||
ErrorKind::InvalidInput,
|
||||
"gzip header field too long",
|
||||
));
|
||||
}
|
||||
Some(byte) => {
|
||||
buffer.push(byte);
|
||||
}
|
||||
None => {
|
||||
return Err(ErrorKind::UnexpectedEof.into());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_le_u16(buffer: &[u8; 2]) -> u16 {
|
||||
(buffer[0] as u16) | ((buffer[1] as u16) << 8)
|
||||
}
|
||||
|
||||
fn bad_header() -> Error {
|
||||
Error::new(ErrorKind::InvalidInput, "invalid gzip header")
|
||||
}
|
||||
|
||||
fn corrupt() -> Error {
|
||||
Error::new(
|
||||
ErrorKind::InvalidInput,
|
||||
"corrupt gzip stream does not have a matching checksum",
|
||||
)
|
||||
}
|
||||
|
||||
/// 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<Vec<u8>>,
|
||||
filename: Option<CString>,
|
||||
comment: Option<CString>,
|
||||
operating_system: Option<u8>,
|
||||
mtime: u32,
|
||||
}
|
||||
|
||||
impl Default for GzBuilder {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
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<T: Into<Vec<u8>>>(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<T: Into<Vec<u8>>>(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<T: Into<Vec<u8>>>(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<W: Write>(self, w: W, lvl: Compression) -> write::GzEncoder<W> {
|
||||
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<R: Read>(self, r: R, lvl: Compression) -> read::GzEncoder<R> {
|
||||
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<R>(self, r: R, lvl: Compression) -> bufread::GzEncoder<R>
|
||||
where
|
||||
R: BufRead,
|
||||
{
|
||||
bufread::gz_encoder(self.into_header(lvl), r, lvl)
|
||||
}
|
||||
|
||||
fn into_header(self, lvl: Compression) -> Vec<u8> {
|
||||
let GzBuilder {
|
||||
extra,
|
||||
filename,
|
||||
comment,
|
||||
operating_system,
|
||||
mtime,
|
||||
} = self;
|
||||
let mut flg = 0;
|
||||
let mut header = vec![0u8; 10];
|
||||
if let Some(v) = extra {
|
||||
flg |= FEXTRA;
|
||||
header.push((v.len() >> 0) as u8);
|
||||
header.push((v.len() >> 8) as u8);
|
||||
header.extend(v);
|
||||
}
|
||||
if let Some(filename) = filename {
|
||||
flg |= FNAME;
|
||||
header.extend(filename.as_bytes_with_nul().iter().copied());
|
||||
}
|
||||
if let Some(comment) = comment {
|
||||
flg |= FCOMMENT;
|
||||
header.extend(comment.as_bytes_with_nul().iter().copied());
|
||||
}
|
||||
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);
|
||||
header
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::io::prelude::*;
|
||||
|
||||
use super::{read, write, GzBuilder, GzHeaderParser};
|
||||
use crate::{Compression, GzHeader};
|
||||
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::<Vec<_>>();
|
||||
for _ in 0..200 {
|
||||
let to_write = &v[..thread_rng().gen_range(0..v.len())];
|
||||
real.extend(to_write.iter().copied());
|
||||
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_eq!(v, real);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn roundtrip_big2() {
|
||||
let v = crate::random_bytes().take(1024 * 1024).collect::<Vec<_>>();
|
||||
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_eq!(res, v);
|
||||
}
|
||||
|
||||
// A Rust implementation of CRC that closely matches the C code in RFC1952.
|
||||
// Only use this to create CRCs for tests.
|
||||
struct Rfc1952Crc {
|
||||
/* Table of CRCs of all 8-bit messages. */
|
||||
crc_table: [u32; 256],
|
||||
}
|
||||
|
||||
impl Rfc1952Crc {
|
||||
fn new() -> Self {
|
||||
let mut crc = Rfc1952Crc {
|
||||
crc_table: [0; 256],
|
||||
};
|
||||
/* Make the table for a fast CRC. */
|
||||
for n in 0usize..256 {
|
||||
let mut c = n as u32;
|
||||
for _k in 0..8 {
|
||||
if c & 1 != 0 {
|
||||
c = 0xedb88320 ^ (c >> 1);
|
||||
} else {
|
||||
c = c >> 1;
|
||||
}
|
||||
}
|
||||
crc.crc_table[n] = c;
|
||||
}
|
||||
crc
|
||||
}
|
||||
|
||||
/*
|
||||
Update a running crc with the bytes buf and return
|
||||
the updated crc. The crc should be initialized to zero. Pre- and
|
||||
post-conditioning (one's complement) is performed within this
|
||||
function so it shouldn't be done by the caller.
|
||||
*/
|
||||
fn update_crc(&self, crc: u32, buf: &[u8]) -> u32 {
|
||||
let mut c = crc ^ 0xffffffff;
|
||||
|
||||
for b in buf {
|
||||
c = self.crc_table[(c as u8 ^ *b) as usize] ^ (c >> 8);
|
||||
}
|
||||
c ^ 0xffffffff
|
||||
}
|
||||
|
||||
/* Return the CRC of the bytes buf. */
|
||||
fn crc(&self, buf: &[u8]) -> u32 {
|
||||
self.update_crc(0, buf)
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn roundtrip_header() {
|
||||
let mut header = GzBuilder::new()
|
||||
.mtime(1234)
|
||||
.operating_system(57)
|
||||
.filename("filename")
|
||||
.comment("comment")
|
||||
.into_header(Compression::fast());
|
||||
|
||||
// Add a CRC to the header
|
||||
header[3] = header[3] ^ super::FHCRC;
|
||||
let rfc1952_crc = Rfc1952Crc::new();
|
||||
let crc32 = rfc1952_crc.crc(&header);
|
||||
let crc16 = crc32 as u16;
|
||||
header.extend(&crc16.to_le_bytes());
|
||||
|
||||
let mut parser = GzHeaderParser::new();
|
||||
parser.parse(&mut header.as_slice()).unwrap();
|
||||
let actual = parser.header().unwrap();
|
||||
assert_eq!(
|
||||
actual,
|
||||
&GzHeader {
|
||||
extra: None,
|
||||
filename: Some("filename".as_bytes().to_vec()),
|
||||
comment: Some("comment".as_bytes().to_vec()),
|
||||
operating_system: 57,
|
||||
mtime: 1234
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
#[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<u8>) -> 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();
|
||||
}
|
||||
}
|
378
vendor/flate2/src/gz/read.rs
vendored
Normal file
378
vendor/flate2/src/gz/read.rs
vendored
Normal file
@ -0,0 +1,378 @@
|
||||
use std::io;
|
||||
use std::io::prelude::*;
|
||||
|
||||
use super::bufread;
|
||||
use super::{GzBuilder, GzHeader};
|
||||
use crate::bufreader::BufReader;
|
||||
use crate::Compression;
|
||||
|
||||
/// A gzip streaming encoder
|
||||
///
|
||||
/// This structure implements a [`Read`] interface. When read from, it reads
|
||||
/// uncompressed data from the underlying [`Read`] and provides the 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::GzEncoder;
|
||||
///
|
||||
/// // Return a vector containing the GZ compressed version of hello world
|
||||
///
|
||||
/// fn gzencode_hello_world() -> io::Result<Vec<u8>> {
|
||||
/// let mut ret_vec = Vec::new();
|
||||
/// let bytestring = b"hello world";
|
||||
/// let mut gz = GzEncoder::new(&bytestring[..], Compression::fast());
|
||||
/// gz.read_to_end(&mut ret_vec)?;
|
||||
/// Ok(ret_vec)
|
||||
/// }
|
||||
/// ```
|
||||
#[derive(Debug)]
|
||||
pub struct GzEncoder<R> {
|
||||
inner: bufread::GzEncoder<BufReader<R>>,
|
||||
}
|
||||
|
||||
pub fn gz_encoder<R: Read>(inner: bufread::GzEncoder<BufReader<R>>) -> GzEncoder<R> {
|
||||
GzEncoder { inner }
|
||||
}
|
||||
|
||||
impl<R: Read> GzEncoder<R> {
|
||||
/// 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<R> {
|
||||
GzBuilder::new().read(r, level)
|
||||
}
|
||||
}
|
||||
|
||||
impl<R> GzEncoder<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 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<R: Read> Read for GzEncoder<R> {
|
||||
fn read(&mut self, into: &mut [u8]) -> io::Result<usize> {
|
||||
self.inner.read(into)
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: Read + Write> Write for GzEncoder<R> {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
self.get_mut().write(buf)
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
self.get_mut().flush()
|
||||
}
|
||||
}
|
||||
|
||||
/// A decoder for a single member of a [gzip file].
|
||||
///
|
||||
/// This structure implements a [`Read`] interface. When read from, it reads
|
||||
/// compressed data from the underlying [`Read`] and provides the uncompressed data.
|
||||
///
|
||||
/// After reading a single member of the gzip data this reader will return
|
||||
/// Ok(0) even if there are more bytes available in the underlying reader.
|
||||
/// `GzDecoder` may have read additional bytes past the end of the gzip data.
|
||||
/// If you need the following bytes, wrap the `Reader` in a `std::io::BufReader`
|
||||
/// and use `bufread::GzDecoder` instead.
|
||||
///
|
||||
/// To handle gzip files that may have multiple members, see [`MultiGzDecoder`]
|
||||
/// or read more
|
||||
/// [in the introduction](../index.html#about-multi-member-gzip-files).
|
||||
///
|
||||
/// [gzip file]: https://www.rfc-editor.org/rfc/rfc1952#page-5
|
||||
///
|
||||
/// # 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<u8>) -> io::Result<String> {
|
||||
/// let mut gz = GzDecoder::new(&bytes[..]);
|
||||
/// let mut s = String::new();
|
||||
/// gz.read_to_string(&mut s)?;
|
||||
/// Ok(s)
|
||||
/// }
|
||||
/// ```
|
||||
#[derive(Debug)]
|
||||
pub struct GzDecoder<R> {
|
||||
inner: bufread::GzDecoder<BufReader<R>>,
|
||||
}
|
||||
|
||||
impl<R: Read> GzDecoder<R> {
|
||||
/// Creates a new decoder from the given reader, immediately parsing the
|
||||
/// gzip header.
|
||||
pub fn new(r: R) -> GzDecoder<R> {
|
||||
GzDecoder {
|
||||
inner: bufread::GzDecoder::new(BufReader::new(r)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<R> GzDecoder<R> {
|
||||
/// 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.
|
||||
///
|
||||
/// Note that the decoder may have read past the end of the gzip data.
|
||||
/// To prevent this use [`bufread::GzDecoder`] instead.
|
||||
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 decoder continues to be used.
|
||||
///
|
||||
/// Note that the decoder may have read past the end of the gzip data.
|
||||
/// To prevent this use [`bufread::GzDecoder`] instead.
|
||||
pub fn get_mut(&mut self) -> &mut R {
|
||||
self.inner.get_mut().get_mut()
|
||||
}
|
||||
|
||||
/// Consumes this decoder, returning the underlying reader.
|
||||
///
|
||||
/// Note that the decoder may have read past the end of the gzip data.
|
||||
/// Subsequent reads will skip those bytes. To prevent this use
|
||||
/// [`bufread::GzDecoder`] instead.
|
||||
pub fn into_inner(self) -> R {
|
||||
self.inner.into_inner().into_inner()
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: Read> Read for GzDecoder<R> {
|
||||
fn read(&mut self, into: &mut [u8]) -> io::Result<usize> {
|
||||
self.inner.read(into)
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: Read + Write> Write for GzDecoder<R> {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
self.get_mut().write(buf)
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
self.get_mut().flush()
|
||||
}
|
||||
}
|
||||
|
||||
/// A gzip streaming decoder that decodes a [gzip file] that may have multiple members.
|
||||
///
|
||||
/// This structure implements a [`Read`] interface. When read from, it reads
|
||||
/// compressed data from the underlying [`Read`] and provides the uncompressed
|
||||
/// data.
|
||||
///
|
||||
/// A gzip file consists of a series of *members* concatenated one after another.
|
||||
/// MultiGzDecoder decodes all members of a file and returns Ok(0) once the
|
||||
/// underlying reader does.
|
||||
///
|
||||
/// To handle members seperately, see [GzDecoder] or read more
|
||||
/// [in the introduction](../index.html#about-multi-member-gzip-files).
|
||||
///
|
||||
/// [gzip file]: https://www.rfc-editor.org/rfc/rfc1952#page-5
|
||||
///
|
||||
/// # 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<u8>) -> io::Result<String> {
|
||||
/// let mut gz = MultiGzDecoder::new(&bytes[..]);
|
||||
/// let mut s = String::new();
|
||||
/// gz.read_to_string(&mut s)?;
|
||||
/// Ok(s)
|
||||
/// }
|
||||
/// ```
|
||||
#[derive(Debug)]
|
||||
pub struct MultiGzDecoder<R> {
|
||||
inner: bufread::MultiGzDecoder<BufReader<R>>,
|
||||
}
|
||||
|
||||
impl<R: Read> MultiGzDecoder<R> {
|
||||
/// 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<R> {
|
||||
MultiGzDecoder {
|
||||
inner: bufread::MultiGzDecoder::new(BufReader::new(r)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<R> MultiGzDecoder<R> {
|
||||
/// 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 decoder 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<R: Read> Read for MultiGzDecoder<R> {
|
||||
fn read(&mut self, into: &mut [u8]) -> io::Result<usize> {
|
||||
self.inner.read(into)
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: Read + Write> Write for MultiGzDecoder<R> {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
self.get_mut().write(buf)
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
self.get_mut().flush()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::io::{Cursor, ErrorKind, Read, Result, Write};
|
||||
|
||||
use super::GzDecoder;
|
||||
|
||||
//a cursor turning EOF into blocking errors
|
||||
#[derive(Debug)]
|
||||
pub struct BlockingCursor {
|
||||
pub cursor: Cursor<Vec<u8>>,
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
impl Write for BlockingCursor {
|
||||
fn write(&mut self, buf: &[u8]) -> Result<usize> {
|
||||
return self.cursor.write(buf);
|
||||
}
|
||||
fn flush(&mut self) -> Result<()> {
|
||||
return self.cursor.flush();
|
||||
}
|
||||
}
|
||||
|
||||
impl Read for BlockingCursor {
|
||||
fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
|
||||
//use the cursor, except it turns eof into blocking error
|
||||
let r = self.cursor.read(buf);
|
||||
match r {
|
||||
Err(ref err) => {
|
||||
if err.kind() == ErrorKind::UnexpectedEof {
|
||||
return Err(ErrorKind::WouldBlock.into());
|
||||
}
|
||||
}
|
||||
Ok(0) => {
|
||||
//regular EOF turned into blocking error
|
||||
return Err(ErrorKind::WouldBlock.into());
|
||||
}
|
||||
Ok(_n) => {}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
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 = GzDecoder::new(r);
|
||||
let mut out = Vec::with_capacity(7);
|
||||
match decoder.read(&mut out) {
|
||||
Err(e) => {
|
||||
assert_eq!(e.kind(), ErrorKind::WouldBlock);
|
||||
}
|
||||
_ => {
|
||||
panic!("Unexpected result for decoder.read");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
641
vendor/flate2/src/gz/write.rs
vendored
Normal file
641
vendor/flate2/src/gz/write.rs
vendored
Normal file
@ -0,0 +1,641 @@
|
||||
use std::cmp;
|
||||
use std::io;
|
||||
use std::io::prelude::*;
|
||||
|
||||
use super::{corrupt, GzBuilder, GzHeader, GzHeaderParser};
|
||||
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<u8> 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<W: Write> {
|
||||
inner: zio::Writer<W, Compress>,
|
||||
crc: Crc,
|
||||
crc_bytes_written: usize,
|
||||
header: Vec<u8>,
|
||||
}
|
||||
|
||||
pub fn gz_encoder<W: Write>(header: Vec<u8>, w: W, lvl: Compression) -> GzEncoder<W> {
|
||||
GzEncoder {
|
||||
inner: zio::Writer::new(w, Compress::new(lvl, false)),
|
||||
crc: Crc::new(),
|
||||
header,
|
||||
crc_bytes_written: 0,
|
||||
}
|
||||
}
|
||||
|
||||
impl<W: Write> GzEncoder<W> {
|
||||
/// 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<W> {
|
||||
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(), 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<W> {
|
||||
self.try_finish()?;
|
||||
Ok(self.inner.take_inner())
|
||||
}
|
||||
|
||||
fn write_header(&mut self) -> io::Result<()> {
|
||||
while !self.header.is_empty() {
|
||||
let n = self.inner.get_mut().write(&self.header)?;
|
||||
self.header.drain(..n);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<W: Write> Write for GzEncoder<W> {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
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()
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: Read + Write> Read for GzEncoder<R> {
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
self.get_mut().read(buf)
|
||||
}
|
||||
}
|
||||
|
||||
impl<W: Write> Drop for GzEncoder<W> {
|
||||
fn drop(&mut self) {
|
||||
if self.inner.is_present() {
|
||||
let _ = self.try_finish();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A decoder for a single member of a [gzip file].
|
||||
///
|
||||
/// This structure exposes a [`Write`] interface, receiving compressed data and
|
||||
/// writing uncompressed data to the underlying writer.
|
||||
///
|
||||
/// After decoding a single member of the gzip data this writer will return the number of bytes up to
|
||||
/// to the end of the gzip member and subsequent writes will return Ok(0) allowing the caller to
|
||||
/// handle any data following the gzip member.
|
||||
///
|
||||
/// To handle gzip files that may have multiple members, see [`MultiGzDecoder`]
|
||||
/// or read more
|
||||
/// [in the introduction](../index.html#about-multi-member-gzip-files).
|
||||
///
|
||||
/// [gzip file]: https://www.rfc-editor.org/rfc/rfc1952#page-5
|
||||
/// [`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<u8> implements Write
|
||||
/// fn decode_writer(bytes: Vec<u8>) -> io::Result<String> {
|
||||
/// 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<W: Write> {
|
||||
inner: zio::Writer<CrcWriter<W>, Decompress>,
|
||||
crc_bytes: Vec<u8>,
|
||||
header_parser: GzHeaderParser,
|
||||
}
|
||||
|
||||
const CRC_BYTES_LEN: usize = 8;
|
||||
|
||||
impl<W: Write> GzDecoder<W> {
|
||||
/// 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<W> {
|
||||
GzDecoder {
|
||||
inner: zio::Writer::new(CrcWriter::new(w), Decompress::new(false)),
|
||||
crc_bytes: Vec::with_capacity(CRC_BYTES_LEN),
|
||||
header_parser: GzHeaderParser::new(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the header associated with this stream.
|
||||
pub fn header(&self) -> Option<&GzHeader> {
|
||||
self.header_parser.header()
|
||||
}
|
||||
|
||||
/// 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<W> {
|
||||
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() {
|
||||
return Err(corrupt());
|
||||
}
|
||||
if amt != self.inner.get_ref().crc().amount() {
|
||||
return Err(corrupt());
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<W: Write> Write for GzDecoder<W> {
|
||||
fn write(&mut self, mut buf: &[u8]) -> io::Result<usize> {
|
||||
let buflen = buf.len();
|
||||
if self.header().is_none() {
|
||||
match self.header_parser.parse(&mut buf) {
|
||||
Err(err) => {
|
||||
if err.kind() == io::ErrorKind::UnexpectedEof {
|
||||
// all data read but header still not complete
|
||||
Ok(buflen)
|
||||
} else {
|
||||
Err(err)
|
||||
}
|
||||
}
|
||||
Ok(_) => {
|
||||
debug_assert!(self.header().is_some());
|
||||
// buf now contains the unread part of the original buf
|
||||
let n = buflen - buf.len();
|
||||
Ok(n)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let (n, status) = self.inner.write_with_status(buf)?;
|
||||
|
||||
if status == Status::StreamEnd && 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()
|
||||
}
|
||||
}
|
||||
|
||||
impl<W: Read + Write> Read for GzDecoder<W> {
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
self.inner.get_mut().get_mut().read(buf)
|
||||
}
|
||||
}
|
||||
|
||||
/// A gzip streaming decoder that decodes a [gzip file] with multiple members.
|
||||
///
|
||||
/// This structure exposes a [`Write`] interface that will consume compressed data and
|
||||
/// write uncompressed data to the underlying writer.
|
||||
///
|
||||
/// A gzip file consists of a series of *members* concatenated one after another.
|
||||
/// `MultiGzDecoder` decodes all members of a file and writes them to the
|
||||
/// underlying writer one after another.
|
||||
///
|
||||
/// To handle members separately, see [GzDecoder] or read more
|
||||
/// [in the introduction](../index.html#about-multi-member-gzip-files).
|
||||
///
|
||||
/// [gzip file]: https://www.rfc-editor.org/rfc/rfc1952#page-5
|
||||
#[derive(Debug)]
|
||||
pub struct MultiGzDecoder<W: Write> {
|
||||
inner: GzDecoder<W>,
|
||||
}
|
||||
|
||||
impl<W: Write> MultiGzDecoder<W> {
|
||||
/// Creates a new decoder which will write uncompressed data to the stream.
|
||||
/// If the gzip stream contains multiple members all will be decoded.
|
||||
pub fn new(w: W) -> MultiGzDecoder<W> {
|
||||
MultiGzDecoder {
|
||||
inner: GzDecoder::new(w),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the header associated with the current member.
|
||||
pub fn header(&self) -> Option<&GzHeader> {
|
||||
self.inner.header()
|
||||
}
|
||||
|
||||
/// 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()
|
||||
}
|
||||
|
||||
/// 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.try_finish()
|
||||
}
|
||||
|
||||
/// 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(self) -> io::Result<W> {
|
||||
self.inner.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<W: Write> Write for MultiGzDecoder<W> {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
if buf.is_empty() {
|
||||
Ok(0)
|
||||
} else {
|
||||
match self.inner.write(buf) {
|
||||
Ok(0) => {
|
||||
// When the GzDecoder indicates that it has finished
|
||||
// create a new GzDecoder to handle additional data.
|
||||
self.inner.try_finish()?;
|
||||
let w = self.inner.inner.take_inner().into_inner();
|
||||
self.inner = GzDecoder::new(w);
|
||||
self.inner.write(buf)
|
||||
}
|
||||
res => res,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
self.inner.flush()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
const STR: &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_partial_header_filename() {
|
||||
let filename = "test.txt";
|
||||
let mut e = GzBuilder::new()
|
||||
.filename(filename)
|
||||
.read(STR.as_bytes(), Compression::default());
|
||||
let mut bytes = Vec::new();
|
||||
e.read_to_end(&mut bytes).unwrap();
|
||||
|
||||
let mut writer = Vec::new();
|
||||
let mut decoder = GzDecoder::new(writer);
|
||||
assert_eq!(decoder.write(&bytes[..12]).unwrap(), 12);
|
||||
let n = decoder.write(&bytes[12..]).unwrap();
|
||||
if n < bytes.len() - 12 {
|
||||
decoder.write(&bytes[n + 12..]).unwrap();
|
||||
}
|
||||
assert_eq!(
|
||||
decoder.header().unwrap().filename().unwrap(),
|
||||
filename.as_bytes()
|
||||
);
|
||||
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_comment() {
|
||||
let comment = "test comment";
|
||||
let mut e = GzBuilder::new()
|
||||
.comment(comment)
|
||||
.read(STR.as_bytes(), Compression::default());
|
||||
let mut bytes = Vec::new();
|
||||
e.read_to_end(&mut bytes).unwrap();
|
||||
|
||||
let mut writer = Vec::new();
|
||||
let mut decoder = GzDecoder::new(writer);
|
||||
assert_eq!(decoder.write(&bytes[..12]).unwrap(), 12);
|
||||
let n = decoder.write(&bytes[12..]).unwrap();
|
||||
if n < bytes.len() - 12 {
|
||||
decoder.write(&bytes[n + 12..]).unwrap();
|
||||
}
|
||||
assert_eq!(
|
||||
decoder.header().unwrap().comment().unwrap(),
|
||||
comment.as_bytes()
|
||||
);
|
||||
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);
|
||||
}
|
||||
|
||||
// Two or more gzip files concatenated form a multi-member gzip file. MultiGzDecoder will
|
||||
// concatenate the decoded contents of all members.
|
||||
#[test]
|
||||
fn decode_multi_writer() {
|
||||
let mut e = GzEncoder::new(Vec::new(), Compression::default());
|
||||
e.write(STR.as_ref()).unwrap();
|
||||
let bytes = e.finish().unwrap().repeat(2);
|
||||
|
||||
let mut writer = Vec::new();
|
||||
let mut decoder = MultiGzDecoder::new(writer);
|
||||
let mut count = 0;
|
||||
while count < bytes.len() {
|
||||
let n = decoder.write(&bytes[count..]).unwrap();
|
||||
assert!(n != 0);
|
||||
count += n;
|
||||
}
|
||||
writer = decoder.finish().unwrap();
|
||||
let return_string = String::from_utf8(writer).expect("String parsing error");
|
||||
let expected = STR.repeat(2);
|
||||
assert_eq!(return_string, expected);
|
||||
}
|
||||
|
||||
// GzDecoder consumes one gzip member and then returns 0 for subsequent writes, allowing any
|
||||
// additional data to be consumed by the caller.
|
||||
#[test]
|
||||
fn decode_extra_data() {
|
||||
let compressed = {
|
||||
let mut e = GzEncoder::new(Vec::new(), Compression::default());
|
||||
e.write(STR.as_ref()).unwrap();
|
||||
let mut b = e.finish().unwrap();
|
||||
b.push(b'x');
|
||||
b
|
||||
};
|
||||
|
||||
let mut writer = Vec::new();
|
||||
let mut decoder = GzDecoder::new(writer);
|
||||
let mut consumed_bytes = 0;
|
||||
loop {
|
||||
let n = decoder.write(&compressed[consumed_bytes..]).unwrap();
|
||||
if n == 0 {
|
||||
break;
|
||||
}
|
||||
consumed_bytes += n;
|
||||
}
|
||||
writer = decoder.finish().unwrap();
|
||||
let actual = String::from_utf8(writer).expect("String parsing error");
|
||||
assert_eq!(actual, STR);
|
||||
assert_eq!(&compressed[consumed_bytes..], b"x");
|
||||
}
|
||||
}
|
234
vendor/flate2/src/lib.rs
vendored
Normal file
234
vendor/flate2/src/lib.rs
vendored
Normal file
@ -0,0 +1,234 @@
|
||||
//! 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 several 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.
|
||||
//!
|
||||
//! * `zlib` - 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. `zlib-ng-compat` is useful if you're using zlib for compatibility but
|
||||
//! want performance via zlib-ng's zlib-compat mode. `zlib` is useful if something else in your
|
||||
//! dependencies links the original zlib so you cannot use zlib-ng-compat. 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<T>` *also* implements the
|
||||
//! `Write` trait if `T: Write`. That is, the "dual trait" is forwarded directly
|
||||
//! to the underlying object if available.
|
||||
//!
|
||||
//! # About multi-member Gzip files
|
||||
//!
|
||||
//! While most `gzip` files one encounters will have a single *member* that can be read
|
||||
//! with the [`GzDecoder`], there may be some files which have multiple members.
|
||||
//!
|
||||
//! A [`GzDecoder`] will only read the first member of gzip data, which may unexpectedly
|
||||
//! provide partial results when a multi-member gzip file is encountered. `GzDecoder` is appropriate
|
||||
//! for data that is designed to be read as single members from a multi-member file. `bufread::GzDecoder`
|
||||
//! and `write::GzDecoder` also allow non-gzip data following gzip data to be handled.
|
||||
//!
|
||||
//! The [`MultiGzDecoder`] on the other hand will decode all members of a `gzip` file
|
||||
//! into one consecutive stream of bytes, which hides the underlying *members* entirely.
|
||||
//! If a file contains contains non-gzip data after the gzip data, MultiGzDecoder will
|
||||
//! emit an error after decoding the gzip data. This behavior matches the `gzip`,
|
||||
//! `gunzip`, and `zcat` command line tools.
|
||||
//!
|
||||
//! [`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
|
||||
//! [`GzDecoder`]: read/struct.GzDecoder.html
|
||||
//! [`MultiGzDecoder`]: read/struct.MultiGzDecoder.html
|
||||
#![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))]
|
||||
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
|
||||
|
||||
#[cfg(not(feature = "any_impl",))]
|
||||
compile_error!("You need to choose a zlib backend");
|
||||
|
||||
pub use crate::crc::{Crc, CrcReader, CrcWriter};
|
||||
pub use crate::gz::GzBuilder;
|
||||
pub use crate::gz::GzHeader;
|
||||
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.
|
||||
///
|
||||
/// Note that the `read` decoder types may read past the end of the compressed
|
||||
/// data while decoding. If the caller requires subsequent reads to start
|
||||
/// immediately following the compressed data wrap the `Read` type in a
|
||||
/// [`BufReader`] and use the `BufReader` with the equivalent decoder from the
|
||||
/// `bufread` module and also for the subsequent reads.
|
||||
///
|
||||
/// [`Read`]: https://doc.rust-lang.org/std/io/trait.Read.html
|
||||
/// [`BufReader`]: https://doc.rust-lang.org/std/io/struct.BufReader.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::gz::write::MultiGzDecoder;
|
||||
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<T: Send + Sync>() {}
|
||||
|
||||
_assert_send_sync::<read::DeflateEncoder<&[u8]>>();
|
||||
_assert_send_sync::<read::DeflateDecoder<&[u8]>>();
|
||||
_assert_send_sync::<read::ZlibEncoder<&[u8]>>();
|
||||
_assert_send_sync::<read::ZlibDecoder<&[u8]>>();
|
||||
_assert_send_sync::<read::GzEncoder<&[u8]>>();
|
||||
_assert_send_sync::<read::GzDecoder<&[u8]>>();
|
||||
_assert_send_sync::<read::MultiGzDecoder<&[u8]>>();
|
||||
_assert_send_sync::<write::DeflateEncoder<Vec<u8>>>();
|
||||
_assert_send_sync::<write::DeflateDecoder<Vec<u8>>>();
|
||||
_assert_send_sync::<write::ZlibEncoder<Vec<u8>>>();
|
||||
_assert_send_sync::<write::ZlibDecoder<Vec<u8>>>();
|
||||
_assert_send_sync::<write::GzEncoder<Vec<u8>>>();
|
||||
_assert_send_sync::<write::GzDecoder<Vec<u8>>>();
|
||||
}
|
||||
|
||||
/// When compressing data, the compression level can be specified by a value in
|
||||
/// this struct.
|
||||
#[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<Item = u8> {
|
||||
use rand::Rng;
|
||||
use std::iter;
|
||||
|
||||
iter::repeat(()).map(|_| rand::thread_rng().gen())
|
||||
}
|
772
vendor/flate2/src/mem.rs
vendored
Normal file
772
vendor/flate2/src/mem.rs
vendored
Normal file
@ -0,0 +1,772 @@
|
||||
use std::error::Error;
|
||||
use std::fmt;
|
||||
use std::io;
|
||||
|
||||
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,
|
||||
}
|
||||
|
||||
/// Values which indicate the form of flushing to be used when compressing
|
||||
/// in-memory data.
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||
#[non_exhaustive]
|
||||
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 decompressor 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,
|
||||
}
|
||||
|
||||
/// Values which indicate the form of flushing to be used when
|
||||
/// decompressing in-memory data.
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||
#[non_exhaustive]
|
||||
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,
|
||||
}
|
||||
|
||||
/// 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<u32> {
|
||||
match self.0 {
|
||||
DecompressErrorInner::NeedsDictionary(adler) => Some(adler),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn decompress_failed<T>(msg: ErrorMessage) -> Result<T, DecompressError> {
|
||||
Err(DecompressError(DecompressErrorInner::General { msg }))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn decompress_need_dict<T>(adler: u32) -> Result<T, DecompressError> {
|
||||
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<T>(msg: ErrorMessage) -> Result<T, CompressError> {
|
||||
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.
|
||||
#[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.
|
||||
#[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<u32, CompressError> {
|
||||
let stream = &mut *self.inner.inner.stream_wrapper;
|
||||
stream.msg = std::ptr::null_mut();
|
||||
let rc = unsafe {
|
||||
assert!(dictionary.len() < ffi::uInt::MAX 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 std::os::raw::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<Status, CompressError> {
|
||||
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<u8>,
|
||||
flush: FlushCompress,
|
||||
) -> Result<Status, CompressError> {
|
||||
write_to_spare_capacity_of_vec(output, |out| {
|
||||
let before = self.total_out();
|
||||
let ret = self.compress(input, out, flush);
|
||||
let bytes_written = self.total_out() - before;
|
||||
(bytes_written as usize, 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.
|
||||
#[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 Decompress 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.
|
||||
#[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<Status, DecompressError> {
|
||||
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<u8>,
|
||||
flush: FlushDecompress,
|
||||
) -> Result<Status, DecompressError> {
|
||||
write_to_spare_capacity_of_vec(output, |out| {
|
||||
let before = self.total_out();
|
||||
let ret = self.decompress(input, out, flush);
|
||||
let bytes_written = self.total_out() - before;
|
||||
(bytes_written as usize, ret)
|
||||
})
|
||||
}
|
||||
|
||||
/// Specifies the decompression dictionary to use.
|
||||
#[cfg(feature = "any_zlib")]
|
||||
pub fn set_dictionary(&mut self, dictionary: &[u8]) -> Result<u32, DecompressError> {
|
||||
let stream = &mut *self.inner.inner.stream_wrapper;
|
||||
stream.msg = std::ptr::null_mut();
|
||||
let rc = unsafe {
|
||||
assert!(dictionary.len() < ffi::uInt::MAX 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<DecompressError> 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<CompressError> 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"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Allows `writer` to write data into the spare capacity of the `output` vector.
|
||||
/// This will not reallocate the vector provided or attempt to grow it, so space
|
||||
/// for the `output` must be reserved by the caller before calling this
|
||||
/// function.
|
||||
///
|
||||
/// `writer` needs to return the number of bytes written (and can also return
|
||||
/// another arbitrary return value).
|
||||
fn write_to_spare_capacity_of_vec<T>(
|
||||
output: &mut Vec<u8>,
|
||||
writer: impl FnOnce(&mut [u8]) -> (usize, T),
|
||||
) -> T {
|
||||
let cap = output.capacity();
|
||||
let len = output.len();
|
||||
|
||||
output.resize(output.capacity(), 0);
|
||||
let (bytes_written, ret) = writer(&mut output[len..]);
|
||||
|
||||
let new_len = core::cmp::min(len + bytes_written, cap); // Sanitizes `bytes_written`.
|
||||
output.resize(new_len, 0 /* unused */);
|
||||
|
||||
ret
|
||||
}
|
||||
|
||||
#[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"));
|
||||
}
|
||||
}
|
286
vendor/flate2/src/zio.rs
vendored
Normal file
286
vendor/flate2/src/zio.rs
vendored
Normal file
@ -0,0 +1,286 @@
|
||||
use std::io;
|
||||
use std::io::prelude::*;
|
||||
use std::mem;
|
||||
|
||||
use crate::{Compress, Decompress, DecompressError, FlushCompress, FlushDecompress, Status};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Writer<W: Write, D: Ops> {
|
||||
obj: Option<W>,
|
||||
pub data: D,
|
||||
buf: Vec<u8>,
|
||||
}
|
||||
|
||||
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<Status, DecompressError>;
|
||||
fn run_vec(
|
||||
&mut self,
|
||||
input: &[u8],
|
||||
output: &mut Vec<u8>,
|
||||
flush: Self::Flush,
|
||||
) -> Result<Status, DecompressError>;
|
||||
}
|
||||
|
||||
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<Status, DecompressError> {
|
||||
Ok(self.compress(input, output, flush).unwrap())
|
||||
}
|
||||
fn run_vec(
|
||||
&mut self,
|
||||
input: &[u8],
|
||||
output: &mut Vec<u8>,
|
||||
flush: FlushCompress,
|
||||
) -> Result<Status, DecompressError> {
|
||||
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<Status, DecompressError> {
|
||||
self.decompress(input, output, flush)
|
||||
}
|
||||
fn run_vec(
|
||||
&mut self,
|
||||
input: &[u8],
|
||||
output: &mut Vec<u8>,
|
||||
flush: FlushDecompress,
|
||||
) -> Result<Status, DecompressError> {
|
||||
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<R, D>(obj: &mut R, data: &mut D, dst: &mut [u8]) -> io::Result<usize>
|
||||
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 | Status::BufError) if read == 0 && !eof && !dst.is_empty() => continue,
|
||||
Ok(Status::Ok | Status::BufError | Status::StreamEnd) => return Ok(read),
|
||||
|
||||
Err(..) => {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::InvalidInput,
|
||||
"corrupt deflate stream",
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<W: Write, D: Ops> Writer<W, D> {
|
||||
pub fn new(w: W, d: D) -> Writer<W, D> {
|
||||
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 = matches!(ret, Ok(Status::StreamEnd));
|
||||
|
||||
if !buf.is_empty() && 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.is_empty() {
|
||||
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<W: Write, D: Ops> Write for Writer<W, D> {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
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<W: Write, D: Ops> Drop for Writer<W, D> {
|
||||
fn drop(&mut self) {
|
||||
if self.obj.is_some() {
|
||||
let _ = self.finish();
|
||||
}
|
||||
}
|
||||
}
|
253
vendor/flate2/src/zlib/bufread.rs
vendored
Normal file
253
vendor/flate2/src/zlib/bufread.rs
vendored
Normal file
@ -0,0 +1,253 @@
|
||||
use std::io;
|
||||
use std::io::prelude::*;
|
||||
use std::mem;
|
||||
|
||||
use crate::zio;
|
||||
use crate::{Compress, Decompress};
|
||||
|
||||
/// A ZLIB encoder, or compressor.
|
||||
///
|
||||
/// This structure implements a [`Read`] interface. When read from, it reads
|
||||
/// uncompressed data from the underlying [`BufRead`] and provides the compressed data.
|
||||
///
|
||||
/// [`Read`]: https://doc.rust-lang.org/std/io/trait.Read.html
|
||||
/// [`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<u8>
|
||||
///
|
||||
/// # fn open_hello_world() -> std::io::Result<Vec<u8>> {
|
||||
/// 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<R> {
|
||||
obj: R,
|
||||
data: Compress,
|
||||
}
|
||||
|
||||
impl<R: BufRead> ZlibEncoder<R> {
|
||||
/// 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<R> {
|
||||
ZlibEncoder {
|
||||
obj: r,
|
||||
data: Compress::new(level, true),
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a new encoder with the given `compression` settings which will
|
||||
/// read uncompressed data from the given stream `r` and emit the compressed stream.
|
||||
pub fn new_with_compress(r: R, compression: Compress) -> ZlibEncoder<R> {
|
||||
ZlibEncoder {
|
||||
obj: r,
|
||||
data: compression,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn reset_encoder_data<R>(zlib: &mut ZlibEncoder<R>) {
|
||||
zlib.data.reset()
|
||||
}
|
||||
|
||||
impl<R> ZlibEncoder<R> {
|
||||
/// 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<R: BufRead> Read for ZlibEncoder<R> {
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
zio::read(&mut self.obj, &mut self.data, buf)
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: BufRead + Write> Write for ZlibEncoder<R> {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
self.get_mut().write(buf)
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
self.get_mut().flush()
|
||||
}
|
||||
}
|
||||
|
||||
/// A ZLIB decoder, or decompressor.
|
||||
///
|
||||
/// This structure implements a [`Read`] interface. When read from, it reads
|
||||
/// compressed data from the underlying [`BufRead`] and provides the uncompressed data.
|
||||
///
|
||||
/// [`Read`]: https://doc.rust-lang.org/std/io/trait.Read.html
|
||||
/// [`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<u8>) -> io::Result<String> {
|
||||
/// let mut z = ZlibDecoder::new(&bytes[..]);
|
||||
/// let mut s = String::new();
|
||||
/// z.read_to_string(&mut s)?;
|
||||
/// Ok(s)
|
||||
/// }
|
||||
/// ```
|
||||
#[derive(Debug)]
|
||||
pub struct ZlibDecoder<R> {
|
||||
obj: R,
|
||||
data: Decompress,
|
||||
}
|
||||
|
||||
impl<R: BufRead> ZlibDecoder<R> {
|
||||
/// Creates a new decoder which will decompress data read from the given
|
||||
/// stream.
|
||||
pub fn new(r: R) -> ZlibDecoder<R> {
|
||||
ZlibDecoder {
|
||||
obj: r,
|
||||
data: Decompress::new(true),
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a new decoder which will decompress data read from the given
|
||||
/// stream, using the given `decompression` settings.
|
||||
pub fn new_with_decompress(r: R, decompression: Decompress) -> ZlibDecoder<R> {
|
||||
ZlibDecoder {
|
||||
obj: r,
|
||||
data: decompression,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn reset_decoder_data<R>(zlib: &mut ZlibDecoder<R>) {
|
||||
zlib.data = Decompress::new(true);
|
||||
}
|
||||
|
||||
impl<R> ZlibDecoder<R> {
|
||||
/// 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 decoder 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<R: BufRead> Read for ZlibDecoder<R> {
|
||||
fn read(&mut self, into: &mut [u8]) -> io::Result<usize> {
|
||||
zio::read(&mut self.obj, &mut self.data, into)
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: BufRead + Write> Write for ZlibDecoder<R> {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
self.get_mut().write(buf)
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
self.get_mut().flush()
|
||||
}
|
||||
}
|
159
vendor/flate2/src/zlib/mod.rs
vendored
Normal file
159
vendor/flate2/src/zlib/mod.rs
vendored
Normal file
@ -0,0 +1,159 @@
|
||||
pub 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::<Vec<_>>();
|
||||
for _ in 0..200 {
|
||||
let to_write = &v[..thread_rng().gen_range(0..v.len())];
|
||||
real.extend(to_write.iter().copied());
|
||||
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_eq!(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_eq!(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::<Vec<_>>();
|
||||
for _ in 0..200 {
|
||||
let to_write = &v[..thread_rng().gen_range(0..v.len())];
|
||||
real.extend(to_write.iter().copied());
|
||||
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().copied());
|
||||
}
|
||||
|
||||
let mut r = read::ZlibDecoder::new(&result[..]);
|
||||
let mut ret = Vec::new();
|
||||
r.read_to_end(&mut ret).unwrap();
|
||||
assert_eq!(ret, real);
|
||||
assert_eq!(r.total_in(), result_len as u64);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn roundtrip2() {
|
||||
let v = crate::random_bytes().take(1024 * 1024).collect::<Vec<_>>();
|
||||
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::<Vec<_>>();
|
||||
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_eq!(w, v);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn reset_decoder() {
|
||||
let v = crate::random_bytes().take(1024 * 1024).collect::<Vec<_>>();
|
||||
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<u8> = Vec::new();
|
||||
let data: Vec<u8> = (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<u8>) -> 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<u8>) -> 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()
|
||||
}
|
||||
}
|
||||
}
|
275
vendor/flate2/src/zlib/read.rs
vendored
Normal file
275
vendor/flate2/src/zlib/read.rs
vendored
Normal file
@ -0,0 +1,275 @@
|
||||
use std::io;
|
||||
use std::io::prelude::*;
|
||||
|
||||
use super::bufread;
|
||||
use crate::bufreader::BufReader;
|
||||
use crate::Decompress;
|
||||
|
||||
/// A ZLIB encoder, or compressor.
|
||||
///
|
||||
/// This structure implements a [`Read`] interface. When read from, it reads
|
||||
/// uncompressed data from the underlying [`Read`] and provides the 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<Vec<u8>> {
|
||||
/// let f = File::open("examples/hello_world.txt")?;
|
||||
/// let mut z = ZlibEncoder::new(f, Compression::fast());
|
||||
/// let mut buffer = Vec::new();
|
||||
/// z.read_to_end(&mut buffer)?;
|
||||
/// # Ok(buffer)
|
||||
/// # }
|
||||
/// ```
|
||||
#[derive(Debug)]
|
||||
pub struct ZlibEncoder<R> {
|
||||
inner: bufread::ZlibEncoder<BufReader<R>>,
|
||||
}
|
||||
|
||||
impl<R: Read> ZlibEncoder<R> {
|
||||
/// 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<R> {
|
||||
ZlibEncoder {
|
||||
inner: bufread::ZlibEncoder::new(BufReader::new(r), level),
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a new encoder with the given `compression` settings which will
|
||||
/// read uncompressed data from the given stream `r` and emit the compressed stream.
|
||||
pub fn new_with_compress(r: R, compression: crate::Compress) -> ZlibEncoder<R> {
|
||||
ZlibEncoder {
|
||||
inner: bufread::ZlibEncoder::new_with_compress(BufReader::new(r), compression),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<R> ZlibEncoder<R> {
|
||||
/// 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<R: Read> Read for ZlibEncoder<R> {
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
self.inner.read(buf)
|
||||
}
|
||||
}
|
||||
|
||||
impl<W: Read + Write> Write for ZlibEncoder<W> {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
self.get_mut().write(buf)
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
self.get_mut().flush()
|
||||
}
|
||||
}
|
||||
|
||||
/// A ZLIB decoder, or decompressor.
|
||||
///
|
||||
/// This structure implements a [`Read`] interface. When read from, it reads
|
||||
/// compressed data from the underlying [`Read`] and provides the 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::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<u8>) -> io::Result<String> {
|
||||
/// let mut z = ZlibDecoder::new(&bytes[..]);
|
||||
/// let mut s = String::new();
|
||||
/// z.read_to_string(&mut s)?;
|
||||
/// Ok(s)
|
||||
/// }
|
||||
/// ```
|
||||
#[derive(Debug)]
|
||||
pub struct ZlibDecoder<R> {
|
||||
inner: bufread::ZlibDecoder<BufReader<R>>,
|
||||
}
|
||||
|
||||
impl<R: Read> ZlibDecoder<R> {
|
||||
/// Creates a new decoder which will decompress data read from the given
|
||||
/// stream.
|
||||
pub fn new(r: R) -> ZlibDecoder<R> {
|
||||
ZlibDecoder::new_with_buf(r, vec![0; 32 * 1024])
|
||||
}
|
||||
|
||||
/// Creates a new decoder which will decompress data read from the given
|
||||
/// stream `r`, using `buf` as backing to speed up reading.
|
||||
///
|
||||
/// 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<u8>) -> ZlibDecoder<R> {
|
||||
ZlibDecoder {
|
||||
inner: bufread::ZlibDecoder::new(BufReader::with_buf(buf, r)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a new decoder which will decompress data read from the given
|
||||
/// stream `r`, along with `decompression` settings.
|
||||
pub fn new_with_decompress(r: R, decompression: Decompress) -> ZlibDecoder<R> {
|
||||
ZlibDecoder::new_with_decompress_and_buf(r, vec![0; 32 * 1024], decompression)
|
||||
}
|
||||
|
||||
/// Creates a new decoder which will decompress data read from the given
|
||||
/// stream `r`, using `buf` as backing to speed up reading,
|
||||
/// along with `decompression` settings to configure decoder.
|
||||
///
|
||||
/// 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_decompress_and_buf(
|
||||
r: R,
|
||||
buf: Vec<u8>,
|
||||
decompression: Decompress,
|
||||
) -> ZlibDecoder<R> {
|
||||
ZlibDecoder {
|
||||
inner: bufread::ZlibDecoder::new_with_decompress(
|
||||
BufReader::with_buf(buf, r),
|
||||
decompression,
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<R> ZlibDecoder<R> {
|
||||
/// 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 decoder 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<R: Read> Read for ZlibDecoder<R> {
|
||||
fn read(&mut self, into: &mut [u8]) -> io::Result<usize> {
|
||||
self.inner.read(into)
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: Read + Write> Write for ZlibDecoder<R> {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
self.get_mut().write(buf)
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
self.get_mut().flush()
|
||||
}
|
||||
}
|
340
vendor/flate2/src/zlib/write.rs
vendored
Normal file
340
vendor/flate2/src/zlib/write.rs
vendored
Normal file
@ -0,0 +1,340 @@
|
||||
use std::io;
|
||||
use std::io::prelude::*;
|
||||
|
||||
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<u8> 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<W: Write> {
|
||||
inner: zio::Writer<W, Compress>,
|
||||
}
|
||||
|
||||
impl<W: Write> ZlibEncoder<W> {
|
||||
/// 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<W> {
|
||||
ZlibEncoder {
|
||||
inner: zio::Writer::new(w, Compress::new(level, true)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a new encoder which will write compressed data to the stream
|
||||
/// `w` with the given `compression` settings.
|
||||
pub fn new_with_compress(w: W, compression: Compress) -> ZlibEncoder<W> {
|
||||
ZlibEncoder {
|
||||
inner: zio::Writer::new(w, compression),
|
||||
}
|
||||
}
|
||||
|
||||
/// 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<W> {
|
||||
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<W> {
|
||||
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<W> {
|
||||
self.inner.flush()?;
|
||||
Ok(self.inner.take_inner())
|
||||
}
|
||||
|
||||
/// Returns the number of bytes that have been written to this compressor.
|
||||
///
|
||||
/// 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<W: Write> Write for ZlibEncoder<W> {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
self.inner.write(buf)
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
self.inner.flush()
|
||||
}
|
||||
}
|
||||
|
||||
impl<W: Read + Write> Read for ZlibEncoder<W> {
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
self.get_mut().read(buf)
|
||||
}
|
||||
}
|
||||
|
||||
/// 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<u8> implements Write
|
||||
///
|
||||
/// fn decode_reader(bytes: Vec<u8>) -> io::Result<String> {
|
||||
/// 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<W: Write> {
|
||||
inner: zio::Writer<W, Decompress>,
|
||||
}
|
||||
|
||||
impl<W: Write> ZlibDecoder<W> {
|
||||
/// 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<W> {
|
||||
ZlibDecoder {
|
||||
inner: zio::Writer::new(w, Decompress::new(true)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a new decoder which will write uncompressed data to the stream `w`
|
||||
/// using the given `decompression` settings.
|
||||
///
|
||||
/// When this decoder is dropped or unwrapped the final pieces of data will
|
||||
/// be flushed.
|
||||
pub fn new_with_decompress(w: W, decompression: Decompress) -> ZlibDecoder<W> {
|
||||
ZlibDecoder {
|
||||
inner: zio::Writer::new(w, decompression),
|
||||
}
|
||||
}
|
||||
|
||||
/// 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<W> {
|
||||
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<W> {
|
||||
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<W: Write> Write for ZlibDecoder<W> {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
self.inner.write(buf)
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
self.inner.flush()
|
||||
}
|
||||
}
|
||||
|
||||
impl<W: Read + Write> Read for ZlibDecoder<W> {
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
self.inner.get_mut().read(buf)
|
||||
}
|
||||
}
|
BIN
vendor/flate2/tests/corrupt-gz-file.bin
vendored
Normal file
BIN
vendor/flate2/tests/corrupt-gz-file.bin
vendored
Normal file
Binary file not shown.
18
vendor/flate2/tests/early-flush.rs
vendored
Normal file
18
vendor/flate2/tests/early-flush.rs
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
use std::io::{Read, Write};
|
||||
|
||||
use flate2::read::GzDecoder;
|
||||
use flate2::write::GzEncoder;
|
||||
|
||||
#[test]
|
||||
fn smoke() {
|
||||
let mut w = GzEncoder::new(Vec::new(), flate2::Compression::default());
|
||||
w.flush().unwrap();
|
||||
w.write_all(b"hello").unwrap();
|
||||
|
||||
let bytes = w.finish().unwrap();
|
||||
|
||||
let mut r = GzDecoder::new(&bytes[..]);
|
||||
let mut s = String::new();
|
||||
r.read_to_string(&mut s).unwrap();
|
||||
assert_eq!(s, "hello");
|
||||
}
|
80
vendor/flate2/tests/empty-read.rs
vendored
Normal file
80
vendor/flate2/tests/empty-read.rs
vendored
Normal file
@ -0,0 +1,80 @@
|
||||
use std::io::{Read, Write};
|
||||
|
||||
#[test]
|
||||
fn deflate_decoder_empty_read() {
|
||||
let original: &[u8] = b"Lorem ipsum dolor sit amet.";
|
||||
let mut encoder =
|
||||
flate2::write::DeflateEncoder::new(Vec::new(), flate2::Compression::default());
|
||||
encoder.write_all(original).unwrap();
|
||||
let encoded: Vec<u8> = 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<u8> = 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<u8> = 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);
|
||||
}
|
BIN
vendor/flate2/tests/good-file.gz
vendored
Normal file
BIN
vendor/flate2/tests/good-file.gz
vendored
Normal file
Binary file not shown.
733
vendor/flate2/tests/good-file.txt
vendored
Normal file
733
vendor/flate2/tests/good-file.txt
vendored
Normal file
@ -0,0 +1,733 @@
|
||||
## ##
|
||||
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
|
75
vendor/flate2/tests/gunzip.rs
vendored
Normal file
75
vendor/flate2/tests/gunzip.rs
vendored
Normal file
@ -0,0 +1,75 @@
|
||||
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_eq!(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<Vec<u8>> {
|
||||
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<Vec<u8>> {
|
||||
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());
|
||||
}
|
BIN
vendor/flate2/tests/multi.gz
vendored
Normal file
BIN
vendor/flate2/tests/multi.gz
vendored
Normal file
Binary file not shown.
2
vendor/flate2/tests/multi.txt
vendored
Normal file
2
vendor/flate2/tests/multi.txt
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
first
|
||||
second
|
6
vendor/flate2/tests/zero-write.rs
vendored
Normal file
6
vendor/flate2/tests/zero-write.rs
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
#[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());
|
||||
}
|
Reference in New Issue
Block a user