flate2-rs icon indicating copy to clipboard operation
flate2-rs copied to clipboard

Decompress Example

Open EricFecteau opened this issue 3 years ago • 0 comments
trafficstars

Receiving zlib raw stream data from python with the "zlib.compressobj(zlib.Z_DEFAULT_COMPRESSION, zlib.DEFLATED, -zlib.MAX_WBITS)" options is not rare, but there are no examples of how to use the "Decompress" object in the example folder and there is no mention of the "Decompress::new_with_window_bits" in the documentation. From my understanding, there is no other way to inflate the below example with this library (since the second "message" is dependent on the first).

Could documentation on the "new_with_window_bits" be added and maybe an example (similar to the one below) be added to the examples?

Python Code for Generating example:

import zlib

compressobj = zlib.compressobj(
    zlib.Z_DEFAULT_COMPRESSION, zlib.DEFLATED, -zlib.MAX_WBITS
)

message = b'{"msgs":[{"msg": "ping"}]}'
compressed = compressobj.compress(message)
compressed += compressobj.flush(zlib.Z_SYNC_FLUSH)
compressed = compressed[:-4]
print([c for c in compressed])

message = b'{"msgs":[{"msg": "lobby_clear"},{"msg": "lobby_complete"}]}'
compressed = compressobj.compress(message)
compressed += compressobj.flush(zlib.Z_SYNC_FLUSH)
compressed = compressed[:-4]
print([c for c in compressed])

Rust Code for inflating the above:

use flate2::{Decompress, FlushDecompress};
use std::str;

fn main() {
    // Python ZLIB compressed with options: zlib.Z_DEFAULT_COMPRESSION, zlib.DEFLATED, -zlib.MAX_WBITS

    // b'{"msgs":[{"msg": "ping"}]}'
    let msg_vec1 = vec![
        170, 86, 202, 45, 78, 47, 86, 178, 138, 174, 6, 49, 148, 172, 20, 148, 10, 50, 243, 210,
        149, 106, 99, 107, 1, 0, 0, 0, 255, 255,
    ];

    // b'{"msgs":[{"msg": "lobby_clear"},{"msg": "lobby_complete"}]}'
    let msg_vec2 = vec![
        170, 198, 144, 201, 201, 79, 74, 170, 140, 79, 206, 73, 77, 44, 82, 170, 213, 65, 23, 206,
        207, 45, 200, 73, 45, 73, 5, 105, 5, 0,
    ];

    let wbits = 15; // Windows bits (goes to -15 in flate2 because of zlib_header = false)
    let bufsize = 32 * 1024;

    let mut decompressor = Decompress::new_with_window_bits(false, wbits);
    let mut decoded_bytes = Vec::with_capacity(bufsize); // with_capacity mandatory, or else err "invalid distance too far back"

    decompressor
        .decompress_vec(&msg_vec1[..], &mut decoded_bytes, FlushDecompress::Finish)
        .expect("Failed to decompress");

    println!("{:?}", str::from_utf8(&decoded_bytes).expect("Bad UTF8"));

    let mut decoded_bytes = Vec::with_capacity(bufsize);
    decompressor
        .decompress_vec(&msg_vec2[..], &mut decoded_bytes, FlushDecompress::Finish)
        .expect("Failed to decompress");

    println!("{:?}", str::from_utf8(&decoded_bytes).expect("Bad UTF8"));
}

Cargo.toml must include the following:

flate2 = { version = "1", features = ["zlib-ng"], default-features = false }

EricFecteau avatar Aug 23 '22 19:08 EricFecteau