compress.deflate #
Description
compress.deflate is a pure V DEFLATE compression and decompression module.
Compression output format is selected by CompressFormat via compress(data, format: ...):
.zlib(RFC 1950 wrapper).gzip(RFC 1952 wrapper).raw_deflate(RFC 1951 raw stream)
compress keeps default zlib behavior, and decompress auto-detects all three.
Testing
Run the module's roundtrip, stream, checksum and malformed-input tests from the repository root:
./v test vlib/compress/deflate/
Example
import compress.deflate
fn main() {
uncompressed := 'Hello world!'
zlib_stream := deflate.compress(uncompressed.bytes())!
gzip_stream := deflate.compress(uncompressed.bytes(), format: .gzip)!
raw_stream := deflate.compress(uncompressed.bytes(), format: .raw_deflate)!
assert deflate.decompress(zlib_stream)! == uncompressed.bytes()
assert deflate.decompress(gzip_stream)! == uncompressed.bytes()
decompressed := deflate.decompress(raw_stream)!
assert decompressed == uncompressed.bytes()
}
Gzip decompression reads all concatenated members and validates each member separately.
A callback returning zero aborts decompression immediately. The returned count covers delivered bytes; unread compressed data and container checksums are not validated after an abort.
Inflation rejects dynamic blocks without an end-of-block code, invalid or incomplete Huffman codes, and code-length repeats beyond the declared alphabets. A literals-only block may omit distance codes; using a length symbol in such a block is an error. The same validation applies to streaming inflation.
Dynamic header validation follows zlib's strict policy: literal/length counts above 286 and distance counts above 30 are rejected. Although the RFC 1951 header can encode 31 or 32 distance codes, these counts are rejected even when the reserved symbols would not appear in the data.
Stored blocks following Huffman blocks retain any complete bytes read ahead by the Huffman decoder. With an otherwise intact zlib or gzip stream, checksum-only corruption is reported as an Adler-32, CRC-32 or uncompressed-size mismatch by one-shot decoding and callbacks that read the whole stream.
validate_zlib_header accepts the two-byte RFC 1950 header and rejects compression info values above 7. Decompression separately rejects streams shorter than the header and Adler-32 trailer, including the callback entry point.
fn compress #
fn compress(data []u8, format CompressParams) ![]u8
compress compresses data as zlib, gzip, or raw DEFLATE.
fn compress_gzip #
fn compress_gzip(data []u8) ![]u8
compress_gzip compresses data into a gzip stream (RFC 1952).
fn compress_raw #
fn compress_raw(data []u8) ![]u8
compress_raw compresses data to a raw RFC 1951 DEFLATE stream.
fn compress_zlib #
fn compress_zlib(data []u8) ![]u8
fn decompress #
fn decompress(data []u8) ![]u8
decompress decompresses a zlib (RFC 1950), gzip (RFC 1952), or raw DEFLATE (RFC 1951) stream. The format is auto-detected.
fn decompress_gzip #
fn decompress_gzip(data []u8) ![]u8
decompress_gzip decompresses all members of a gzip stream (RFC 1952). It returns the concatenated decompressed bytes in a new array.
fn decompress_raw_with_consumed #
fn decompress_raw_with_consumed(data []u8) !RawInflateResult
decompress_raw_with_consumed decompresses raw RFC 1951 DEFLATE data and tracks consumed bytes.
fn decompress_with_callback #
fn decompress_with_callback(data []u8, cb ChunkCallback, userdata voidptr) !int
decompress_with_callback decompresses a zlib/gzip/raw stream (RFC 1950, RFC 1952) using a callback for chunked delivery. The callback receives chunks of decompressed data and should return the chunk length to continue, or 0 to abort. Returns the number of bytes delivered. If the callback aborts, unread data and trailers are not validated.
fn decompress_zlib #
fn decompress_zlib(data []u8) ![]u8
decompress_zlib decompresses a zlib stream (RFC 1950). It returns the decompressed bytes in a new array.
fn validate_gzip_header #
fn validate_gzip_header(data []u8) !GzipHeader
validate_gzip_header validates a RFC 1952 gzip header and returns parsed fields.
fn validate_zlib_header #
fn validate_zlib_header(data []u8) !ZlibHeader
validate_zlib_header validates a RFC 1950 zlib header.
fn CompressFormat.from #
fn CompressFormat.from[W](input W) !CompressFormat
from returns the CompressFormat value of an integer or of a field name, or an error if there is none.
type ChunkCallback #
type ChunkCallback = fn (chunk []u8, userdata voidptr) int
enum CompressFormat #
enum CompressFormat {
zlib
gzip
raw_deflate
}
CompressFormat selects the output container around the RFC 1951 payload.
struct CompressParams #
struct CompressParams {
pub:
format CompressFormat = .zlib
}
struct GzipHeader #
struct GzipHeader {
pub mut:
flags u8
payload_start int
extra []u8
filename []u8
comment []u8
modification_time u32
operating_system u8
}
struct RawInflateResult #
struct RawInflateResult {
pub:
decoded []u8
consumed int
}
struct ZlibHeader #
struct ZlibHeader {
pub:
payload_start int = 2
}
- README
- fn compress
- fn compress_gzip
- fn compress_raw
- fn compress_zlib
- fn decompress
- fn decompress_gzip
- fn decompress_raw_with_consumed
- fn decompress_with_callback
- fn decompress_zlib
- fn validate_gzip_header
- fn validate_zlib_header
- fn CompressFormat.from
- type ChunkCallback
- enum CompressFormat
- struct CompressParams
- struct GzipHeader
- struct RawInflateResult
- struct ZlibHeader