Merge pull request #1243 from mpajkowski/zlib_module

Implement zlib module
This commit is contained in:
Windel Bouwman
2019-08-13 07:12:21 +02:00
committed by GitHub
5 changed files with 298 additions and 0 deletions

76
Cargo.lock generated
View File

@@ -1,5 +1,10 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "adler32"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "aho-corasick"
version = "0.6.10"
@@ -263,6 +268,14 @@ dependencies = [
"build_const 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "crc32fast"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "crossbeam-utils"
version = "0.5.0"
@@ -399,6 +412,17 @@ dependencies = [
"serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "flate2"
version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)",
"libz-sys 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
"miniz_oxide_c_api 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "fnv"
version = "1.0.6"
@@ -563,6 +587,17 @@ name = "libc"
version = "0.2.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "libz-sys"
version = "1.0.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cc 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)",
"pkg-config 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
"vcpkg 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "log"
version = "0.3.9"
@@ -604,6 +639,25 @@ name = "memchr"
version = "2.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "miniz_oxide"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "miniz_oxide_c_api"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cc 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
"crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)",
"miniz_oxide 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "new_debug_unreachable"
version = "1.0.3"
@@ -725,6 +779,11 @@ dependencies = [
"siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "pkg-config"
version = "0.3.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "precomputed-hash"
version = "0.1.1"
@@ -1045,6 +1104,7 @@ dependencies = [
name = "rustpython-vm"
version = "0.1.0"
dependencies = [
"adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
"arr_macro 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"bincode 1.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
"bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1053,9 +1113,11 @@ dependencies = [
"caseless 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
"crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
"flame 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"flamer 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"flate2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
"gethostname 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"hexf-parse 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1064,6 +1126,7 @@ dependencies = [
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"lexical 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)",
"libz-sys 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"md-5 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1734,6 +1797,11 @@ name = "utf8parse"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "vcpkg"
version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "vec_map"
version = "0.8.1"
@@ -1899,6 +1967,7 @@ version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[metadata]
"checksum adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7e522997b529f05601e05166c07ed17789691f562762c7f3b987263d2dedee5c"
"checksum aho-corasick 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "81ce3d38065e618af2d7b77e10c5ad9a069859b4be3c2250f674af3840d9c8a5"
"checksum aho-corasick 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "36b7aa1ccb7d7ea3f437cf025a2ab1c47cc6c1bc9fc84918ff449def12f5e282"
"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
@@ -1932,6 +2001,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e"
"checksum cpython 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b489034e723e7f5109fecd19b719e664f89ef925be785885252469e9822fa940"
"checksum crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d663548de7f5cca343f1e0a48d14dcfb0e9eb4e079ec58883b7251539fa10aeb"
"checksum crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1"
"checksum crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "677d453a17e8bd2b913fa38e8b9cf04bcdbb5be790aa294f2389661d72036015"
"checksum crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4434400df11d95d556bac068ddfedd482915eb18fe8bea89bc80b6e4b1c179e5"
"checksum diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "3c2b69f912779fbb121ceb775d74d51e915af17aaebc38d28a592843a2dd0a3a"
@@ -1948,6 +2018,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum flame 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1fc2706461e1ee94f55cab2ed2e3d34ae9536cfa830358ef80acff1a3dacab30"
"checksum flamer 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f2add1a5e84b1ed7b5d00cdc21789a28e0a8f4e427b677313c773880ba3c4dac"
"checksum flamescope 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6e3e6aee625a28b97be4308bccc2eb5f81d9ec606b3f29e13c0f459ce20dd136"
"checksum flate2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "550934ad4808d5d39365e5d61727309bf18b3b02c6c56b729cb92e7dd84bc3d8"
"checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3"
"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
"checksum futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "45dc39533a6cae6da2b56da48edae506bb767ec07370f86f70fc062e9d435869"
@@ -1970,12 +2041,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum lexical 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "93de1b2ed9c7f01aac327bf84542a053b6cd15761defdcfaceb27e1d1b871e74"
"checksum lexical-core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3f8673fab7063c2cac37d299c8a1a7beb720e78f71500098e4a3c137fdf025bf"
"checksum libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)" = "d44e80633f007889c7eff624b709ab43c92d708caad982295768a7b13ca3b5eb"
"checksum libz-sys 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "2eb5e43362e38e2bca2fd5f5134c4d4564a23a5c28e9b95411652021a8675ebe"
"checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b"
"checksum log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "c275b6ad54070ac2d665eef9197db647b32239c9d244bfb6f041a766d00da5b3"
"checksum maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "08cbb6b4fef96b6d77bfc40ec491b1690c779e77b05cd9f07f787ed376fd4c43"
"checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08"
"checksum md-5 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a18af3dcaf2b0219366cdb4e2af65a6101457b415c3d1a5c71dd9c2b7c77b9c8"
"checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e"
"checksum miniz_oxide 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7108aff85b876d06f22503dcce091e29f76733b2bfdd91eebce81f5e68203a10"
"checksum miniz_oxide_c_api 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6c675792957b0d19933816c4e1d56663c341dd9bfa31cb2140ff2267c1d8ecf4"
"checksum new_debug_unreachable 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f40f005c60db6e03bae699e414c58bf9aa7ea02a2d0b9bfbcf19286cc4c82b30"
"checksum nix 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4dbdc256eaac2e3bd236d93ad999d3479ef775c863dbda3068c4006a92eec51b"
"checksum nix 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6c722bee1037d430d0f8e687bbdbf222f27cc6e4e68d5caf630857bb2b6dbdce"
@@ -1991,6 +2065,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum petgraph 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)" = "9c3659d1ee90221741f65dd128d9998311b0e40c5d3c23a62445938214abce4f"
"checksum phf_generator 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "09364cc93c159b8b06b1f4dd8a4398984503483891b0c26b867cf431fb132662"
"checksum phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "234f71a15de2288bcb7e3b6515828d22af7ec8598ee6d24c3b526fa0a80b67a0"
"checksum pkg-config 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c1d2cfa5a714db3b5f24f0915e74fcdf91d09d496ba61329705dda7774d2af"
"checksum precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
"checksum proc-macro-hack 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)" = "982a35d1194084ba319d65c4a68d24ca28f5fdb5b8bc20899e4eef8641ea5178"
"checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759"
@@ -2093,6 +2168,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56"
"checksum utf8-ranges 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "9d50aa7650df78abf942826607c62468ce18d9019673d4a2ebe1865dbb96ffde"
"checksum utf8parse 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8772a4ccbb4e89959023bc5b7cb8623a795caa7092d99f3aa9501b9484d4557d"
"checksum vcpkg 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "33dd455d0f96e90a75803cfeb7f948768c08d70a6de9a8d2362461935698bf95"
"checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a"
"checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd"
"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"

View File

@@ -0,0 +1,62 @@
import zlib
from testutils import assert_raises
# checksum functions
assert zlib.crc32(b"123") == 2286445522
assert zlib.crc32(b"123", 1) == 2307525093
assert zlib.crc32(b"123", 2) == 2345449404
assert zlib.crc32(b"123", 3) == 2316230027
assert zlib.crc32(b"123", 4) == 2403453710
assert zlib.crc32(b"123", 5) == 2390991161
assert zlib.crc32(b"123", 6) == 2361728864
assert zlib.crc32(b"123", -123) == 3515918521
assert zlib.crc32(b"123", -122) == 3554023136
assert zlib.crc32(b"123", -121) == 3524558039
assert zlib.crc32(b"123", -120) == 3645389802
assert zlib.crc32(b"123", -119) == 3632943581
assert zlib.crc32(b"123", -118) == 3670863748
assert zlib.crc32(b"123") == zlib.crc32(b"123", 0)
assert zlib.adler32(b"456") == 20906144
assert zlib.adler32(b"456", 1) == 20906144
assert zlib.adler32(b"456", 2) == 21102753
assert zlib.adler32(b"456", 3) == 21299362
assert zlib.adler32(b"456", 4) == 21495971
assert zlib.adler32(b"456", 5) == 21692580
assert zlib.adler32(b"456", 6) == 21889189
assert zlib.adler32(b"456", -123) == 393267
assert zlib.adler32(b"456", -122) == 589876
assert zlib.adler32(b"456", -121) == 786485
assert zlib.adler32(b"456", -120) == 983094
assert zlib.adler32(b"456", -119) == 1179703
assert zlib.adler32(b"456", -118) == 1376312
assert zlib.adler32(b"456") == zlib.adler32(b"456", 1)
# compression
lorem = bytes("Lorem ipsum dolor sit amet", "utf-8")
compressed_lorem_list = [
b"x\x01\x01\x1a\x00\xe5\xffLorem ipsum dolor sit amet\x83\xd5\t\xc5",
b"x\x01\xf3\xc9/J\xcdU\xc8,(.\xcdUH\xc9\xcf\xc9/R(\xce,QH\xccM-\x01\x00\x83\xd5\t\xc5",
b"x^\xf3\xc9/J\xcdU\xc8,(.\xcdUH\xc9\xcf\xc9/R(\xce,QH\xccM-\x01\x00\x83\xd5\t\xc5",
b"x^\xf3\xc9/J\xcdU\xc8,(.\xcdUH\xc9\xcf\xc9/R(\xce,QH\xccM-\x01\x00\x83\xd5\t\xc5",
b"x^\xf3\xc9/J\xcdU\xc8,(.\xcdUH\xc9\xcf\xc9/R(\xce,QH\xccM-\x01\x00\x83\xd5\t\xc5",
b"x^\xf3\xc9/J\xcdU\xc8,(.\xcdUH\xc9\xcf\xc9/R(\xce,QH\xccM-\x01\x00\x83\xd5\t\xc5",
b"x\x9c\xf3\xc9/J\xcdU\xc8,(.\xcdUH\xc9\xcf\xc9/R(\xce,QH\xccM-\x01\x00\x83\xd5\t\xc5",
b"x\xda\xf3\xc9/J\xcdU\xc8,(.\xcdUH\xc9\xcf\xc9/R(\xce,QH\xccM-\x01\x00\x83\xd5\t\xc5",
b"x\xda\xf3\xc9/J\xcdU\xc8,(.\xcdUH\xc9\xcf\xc9/R(\xce,QH\xccM-\x01\x00\x83\xd5\t\xc5",
b"x\xda\xf3\xc9/J\xcdU\xc8,(.\xcdUH\xc9\xcf\xc9/R(\xce,QH\xccM-\x01\x00\x83\xd5\t\xc5",
]
for level, text in enumerate(compressed_lorem_list):
assert zlib.compress(lorem, level) == text
# default level
assert zlib.compress(lorem) == zlib.compress(lorem, -1) == zlib.compress(lorem, 6)
# decompression
for text in compressed_lorem_list:
assert zlib.decompress(text) == lorem
assert_raises(zlib.error, lambda: zlib.compress(b"123", -40))
assert_raises(zlib.error, lambda: zlib.compress(b"123", 10))

View File

@@ -72,5 +72,9 @@ flamer = { version = "0.3", optional = true }
pwd = "1"
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
crc32fast = "1.2.0"
adler32 = "1.0.3"
flate2 = { version = "1.0", features = ["zlib"], default-features = false }
libz-sys = "1.0.25"
gethostname = "0.2.0"
subprocess = "0.1.18"

View File

@@ -43,6 +43,8 @@ mod pwd;
pub mod signal;
#[cfg(not(target_arch = "wasm32"))]
mod subprocess;
#[cfg(not(target_arch = "wasm32"))]
mod zlib;
use crate::pyobject::PyObjectRef;
@@ -99,6 +101,7 @@ pub fn get_module_inits() -> HashMap<String, StdlibInitFunc> {
modules.insert("socket".to_string(), Box::new(socket::make_module));
modules.insert("signal".to_string(), Box::new(signal::make_module));
modules.insert("subprocess".to_string(), Box::new(subprocess::make_module));
modules.insert("zlib".to_string(), Box::new(zlib::make_module));
}
// Unix-only

153
vm/src/stdlib/zlib.rs Normal file
View File

@@ -0,0 +1,153 @@
use crate::function::OptionalArg;
use crate::obj::{objbytes::PyBytesRef, objint::PyIntRef};
use crate::pyobject::{create_type, ItemProtocol, PyObjectRef, PyResult};
use crate::vm::VirtualMachine;
use adler32::RollingAdler32 as Adler32;
use crc32fast::Hasher as Crc32;
use flate2::{write::ZlibEncoder, Compression, Decompress, FlushDecompress, Status};
use libz_sys as libz;
use num_traits::cast::ToPrimitive;
use std::io::Write;
// copied from zlibmodule.c (commit 530f506ac91338)
const MAX_WBITS: u8 = 15;
const DEF_BUF_SIZE: usize = 16 * 1024;
pub fn make_module(vm: &VirtualMachine) -> PyObjectRef {
let ctx = &vm.ctx;
let zlib_error = create_type("error", &ctx.type_type, &ctx.exceptions.exception_type);
py_module!(vm, "zlib", {
"crc32" => ctx.new_rustfunc(zlib_crc32),
"adler32" => ctx.new_rustfunc(zlib_adler32),
"compress" => ctx.new_rustfunc(zlib_compress),
"decompress" => ctx.new_rustfunc(zlib_decompress),
"error" => zlib_error,
"Z_DEFAULT_COMPRESSION" => ctx.new_int(libz::Z_DEFAULT_COMPRESSION),
"Z_NO_COMPRESSION" => ctx.new_int(libz::Z_NO_COMPRESSION),
"Z_BEST_SPEED" => ctx.new_int(libz::Z_BEST_SPEED),
"Z_BEST_COMPRESSION" => ctx.new_int(libz::Z_BEST_COMPRESSION),
"DEF_BUF_SIZE" => ctx.new_int(DEF_BUF_SIZE),
"MAX_WBITS" => ctx.new_int(MAX_WBITS),
})
}
/// Compute an Adler-32 checksum of data.
fn zlib_adler32(
data: PyBytesRef,
begin_state: OptionalArg<PyIntRef>,
vm: &VirtualMachine,
) -> PyResult<PyObjectRef> {
let data = data.get_value();
let begin_state = begin_state
.into_option()
.as_ref()
.map(|v| v.as_bigint().to_i32().unwrap())
.unwrap_or(1);
let mut hasher = Adler32::from_value(begin_state as u32);
hasher.update_buffer(data);
let checksum: u32 = hasher.hash();
Ok(vm.new_int(checksum))
}
/// Compute a CRC-32 checksum of data.
fn zlib_crc32(
data: PyBytesRef,
begin_state: OptionalArg<PyIntRef>,
vm: &VirtualMachine,
) -> PyResult<PyObjectRef> {
let data = data.get_value();
let begin_state = begin_state
.into_option()
.as_ref()
.map(|v| v.as_bigint().to_i32().unwrap())
.unwrap_or(0);
let mut hasher = Crc32::new_with_initial(begin_state as u32);
hasher.update(data);
let checksum: u32 = hasher.finalize();
Ok(vm.new_int(checksum))
}
/// Returns a bytes object containing compressed data.
fn zlib_compress(
data: PyBytesRef,
level: OptionalArg<PyIntRef>,
vm: &VirtualMachine,
) -> PyResult<PyObjectRef> {
let input_bytes = data.get_value();
let level = level
.into_option()
.as_ref()
.map(|v| v.as_bigint().to_i32().unwrap())
.unwrap_or(libz::Z_DEFAULT_COMPRESSION);
let compression = match level {
valid_level @ libz::Z_NO_COMPRESSION...libz::Z_BEST_COMPRESSION => {
Compression::new(valid_level as u32)
}
libz::Z_DEFAULT_COMPRESSION => Compression::default(),
_ => return Err(zlib_error("Bad compression level", vm)),
};
let mut encoder = ZlibEncoder::new(Vec::new(), compression);
encoder.write_all(input_bytes).unwrap();
let encoded_bytes = encoder.finish().unwrap();
Ok(vm.ctx.new_bytes(encoded_bytes))
}
/// Returns a bytes object containing the uncompressed data.
fn zlib_decompress(
data: PyBytesRef,
wbits: OptionalArg<PyIntRef>,
bufsize: OptionalArg<PyIntRef>,
vm: &VirtualMachine,
) -> PyResult<PyObjectRef> {
let encoded_bytes = data.get_value();
let wbits = wbits
.into_option()
.as_ref()
.map(|wbits| wbits.as_bigint().to_u8().unwrap())
.unwrap_or(MAX_WBITS);
let bufsize = bufsize
.into_option()
.as_ref()
.map(|bufsize| bufsize.as_bigint().to_usize().unwrap())
.unwrap_or(DEF_BUF_SIZE);
let mut decompressor = Decompress::new_with_window_bits(true, wbits);
let mut decoded_bytes = Vec::with_capacity(bufsize);
match decompressor.decompress_vec(&encoded_bytes, &mut decoded_bytes, FlushDecompress::Finish) {
Ok(Status::BufError) => Err(zlib_error("inconsistent or truncated state", vm)),
Err(_) => Err(zlib_error("invalid input data", vm)),
_ => Ok(vm.ctx.new_bytes(decoded_bytes)),
}
}
fn zlib_error(message: &str, vm: &VirtualMachine) -> PyObjectRef {
let module = vm
.get_attribute(vm.sys_module.clone(), "modules")
.unwrap()
.get_item("zlib", vm)
.unwrap();
let zlib_error = vm.get_attribute(module, "error").unwrap();
let zlib_error = zlib_error.downcast().unwrap();
vm.new_exception(zlib_error, message.to_string())
}