std.compress
API summary (generated from the Beans source by npm run coverage): 6 package functions · 3 types · 2 static methods · 5 instance methods · 3 enum variants.
std.compress provides DEFLATE compression in three framings, one-shot and
streaming, over zlib-ng. The source is
stdlib/std/compress/compress.b.
import std.compressRules that shape the package
Section titled “Rules that shape the package”- Decompression limits are mandatory. Every decompression call requires a
maximum output size. It returns an
errwith kindlimitwhen the output would exceed that size. - Three formats are supported.
zlib(RFC 1950),raw(RFC 1951), andgzip(RFC 1952) are selected by name. gzip decoding reads every member of a multi-member file, likegzip -don concatenated archives. - One-shot for buffers, streams for everything else. The module functions
take and return whole
Bytes.DeflaterandInflaterare move-only handles for data arriving in pieces, and anInflater’s limit holds across its whole life rather than per call.
Error kinds you may see: limit (the output bound was crossed), eof (the
stream ends before its data does), invalid (corrupt input, or a missing
limit), memory, closed.
Format
Section titled “Format”pub enum Format { zlib raw gzip}zlib is what most protocols mean by “deflate”; raw is headerless DEFLATE, as
used by WebSocket permessage-deflate and ZIP entries; gzip is the file format.
Module functions
Section titled “Module functions”pub fn deflate(data: Bytes, level: int = 6) -> Result<Bytes>pub fn inflate(data: Bytes, limit: int) -> Result<Bytes>pub fn gzip_compress(data: Bytes, level: int = 6) -> Result<Bytes>pub fn gzip_decompress(data: Bytes, limit: int) -> Result<Bytes>pub fn deflate_raw(data: Bytes, level: int = 6) -> Result<Bytes>pub fn inflate_raw(data: Bytes, limit: int) -> Result<Bytes>level runs 0..9; 6 balances speed against size. Every decompressing function
takes limit as the maximum output it will produce.
let packed: Bytes = compress.gzip_compress(data)?let back: Bytes = compress.gzip_decompress(packed, 1048576)?Deflater
Section titled “Deflater”A streaming compressor. Move-only and Send; finish ends the stream and the handle
refuses further work.
pub unique class Deflater implements Sendpub static fn open(format: Format, level: int = 6) -> Result<Deflater>pub fn push(data: Bytes) -> Result<Bytes>pub fn finish() -> Result<Bytes>push returns whatever output is ready, which is often nothing: DEFLATE buffers
freely until finish.
let press: compress.Deflater = compress.Deflater.open(compress.Format.zlib)?var wire: Bytes = new Bytes(0)wire.append(press.push(first)?)wire.append(press.push(second)?)wire.append(press.finish()?)Inflater
Section titled “Inflater”A move-only, Send streaming decompressor with one limit across its whole life.
pub unique class Inflater implements Sendpub static fn open(format: Format, limit: int) -> Result<Inflater>pub fn push(data: Bytes) -> Result<Bytes>pub fn finished() -> boolpub fn finish() -> Result<Bytes>push decompresses one arriving piece and is kind limit the moment the total
output would cross the bound. finished() is true once the stream announced its
own end — after that, more input is kind invalid. finish declares
end-of-input; a stream cut short is kind eof.
The bomb, and why the limit is a parameter
Section titled “The bomb, and why the limit is a parameter”A quarter megabyte of zeros compresses to a few hundred bytes. A reader that budgeted a kilobyte finds out as an error rather than as memory pressure:
var zeros: Bytes = new Bytes(262144)zeros.fill(0)let bomb: Bytes = compress.deflate(zeros)? // a few hundred bytesmatch compress.inflate(bomb, 1024) { ok(_) => { io.println("unreachable") } err(e) => { io.println(e.kind) } // limit}