packkit/stream
Streaming helpers for codec families.
packkit/stream exposes opaque decoder states that buffer input
chunks and run a one-shot decode at finish time. The API matches
the streaming shape the spec calls for - new_*_decoder, push,
finish - so callers can already wire incremental pipelines even
while the underlying codec decoders are still eager.
Relationship to packkit/codec.Codec. The streaming
constructors (new_gzip_encoder, new_zstd_decoder, …) do NOT
accept a packkit/codec.Codec value, so the per-codec Level /
preset Dictionary settings carried by a Codec are not threaded
through this API; every stream uses the codec’s default encode
strategy. This is intentional: a Codec is the config object
packkit.compress / packkit.decompress (the one-shot facade)
consumes, while packkit/stream only ever invokes the codec
module’s bare encode/1 / decode/1 entry points. Callers that
need a non-default level or a preset dictionary should call the
per-codec module directly (gzip.encode_with_header,
zlib.encode_with_dictionary, deflate.encode_dynamic, …) and
drive the chunking themselves until the streaming API grows
codec-typed constructors. The Limits value, by contrast, IS
honoured incrementally — see [push] / [push_encoder].
Types
Opaque incremental decoder state. The wrapped codec selector is
kept private; callers should construct one of the new_*_decoder
values and feed it through push/finish.
buffered_bytes is tracked so push can enforce max_input_bytes
incrementally — a hostile or buggy producer can no longer stream
arbitrarily many chunks into the decoder before the budget check
fires at finish time.
pub opaque type Decoder
Opaque incremental encoder state. Mirrors Decoder: callers
buffer plaintext chunks via push_encoder and pay the actual
compress cost once at finish_encoder time. Buffering lets the
API stay symmetric with Decoder even though the underlying
codecs are still eager — when packkit grows true streaming
encoders the public surface won’t have to change.
buffered_bytes is tracked so push_encoder can enforce
max_input_bytes incrementally against the input stream, matching
the decoder-side limit semantics.
pub opaque type Encoder
Values
pub fn decode_chunks(
decoder decoder: Decoder,
chunks chunks: List(BitArray),
) -> Result(BitArray, error.CodecError)
Convenience helper that pushes every chunk through the decoder in
order and returns the final decoded payload. Surfaces the same
typed CodecLimitExceeded push would, so a long sequence of
chunks cannot silently overrun the input budget.
pub fn encode_chunks(
encoder encoder: Encoder,
chunks chunks: List(BitArray),
) -> Result(BitArray, error.CodecError)
Convenience helper that pushes every plaintext chunk through the
encoder in order and returns the final compressed payload. Mirrors
decode_chunks so callers can drive both directions with the same
shape (list of input chunks → single output buffer).
pub fn encoder_with_limits(
encoder: Encoder,
limits limits: limit.Limits,
) -> Encoder
Replace the limits used by an incremental encoder.
pub fn finish(
decoder: Decoder,
) -> Result(BitArray, error.CodecError)
Finalize the decoder and return the full decoded payload.
pub fn finish_encoder(
encoder: Encoder,
) -> Result(BitArray, error.CodecError)
Finalize the encoder and return the compressed payload. Each
codec is invoked through its default encode/1 form; advanced
per-codec options (gzip header metadata, deflate stored blocks,
lz4 content size, bzip2 level) are not exposed through the
streaming wrapper and remain accessible via the per-codec module.
pub fn new_brotli_decoder() -> Decoder
Start a new incremental brotli decoder using the default limits.
pub fn new_brotli_encoder() -> Encoder
Start a new incremental brotli encoder using the default limits.
pub fn new_bzip2_decoder() -> Decoder
Start a new incremental bzip2 decoder using the default limits.
pub fn new_bzip2_encoder() -> Encoder
Start a new incremental bzip2 encoder using the default limits.
pub fn new_deflate_decoder() -> Decoder
Start a new incremental DEFLATE decoder using the default limits.
pub fn new_deflate_encoder() -> Encoder
Start a new incremental DEFLATE encoder using the default limits.
pub fn new_gzip_decoder() -> Decoder
Start a new incremental gzip decoder using the default limits.
pub fn new_gzip_encoder() -> Encoder
Start a new incremental gzip encoder using the default limits.
The output uses gzip.default_header() — callers that need
per-stream metadata should keep using gzip.encode directly
until the streaming API grows an explicit header constructor.
pub fn new_lz4_decoder() -> Decoder
Start a new incremental LZ4 frame decoder using the default limits.
pub fn new_lz4_encoder() -> Encoder
Start a new incremental LZ4 frame encoder using the default limits.
pub fn new_lzw_decoder() -> Decoder
Start a new incremental Unix .Z (LZW) decoder using the default
limits.
pub fn new_lzw_encoder() -> Encoder
Start a new incremental Unix .Z (LZW) encoder using the default
limits.
pub fn new_snappy_decoder() -> Decoder
Start a new incremental Snappy (framed) decoder using the default limits. See [packkit/snappy] for the raw-block variants.
pub fn new_snappy_encoder() -> Encoder
Start a new incremental Snappy (framed) encoder using the default limits.
pub fn new_xz_decoder() -> Decoder
Start a new incremental xz decoder using the default limits.
pub fn new_xz_encoder() -> Encoder
Start a new incremental xz encoder using the default limits.
pub fn new_zlib_decoder() -> Decoder
Start a new incremental zlib decoder using the default limits.
pub fn new_zlib_encoder() -> Encoder
Start a new incremental zlib encoder using the default limits.
pub fn new_zstd_decoder() -> Decoder
Start a new incremental zstd decoder using the default limits.
pub fn new_zstd_encoder() -> Encoder
Start a new incremental zstd encoder using the default limits.
pub fn push(
decoder: Decoder,
chunk: BitArray,
) -> Result(Decoder, error.CodecError)
Append a chunk of input bytes to the decoder, enforcing
max_input_bytes incrementally. Returns a typed
CodecLimitExceeded if the running buffered byte count would
exceed the configured limit.
pub fn push_encoder(
encoder: Encoder,
chunk: BitArray,
) -> Result(Encoder, error.CodecError)
Append a chunk of plaintext bytes to the encoder, enforcing
max_input_bytes incrementally so an unbounded producer can’t
trigger an unbounded encode allocation at finish_encoder time.
pub fn with_limits(
decoder: Decoder,
limits limits: limit.Limits,
) -> Decoder
Replace the limits used by an incremental decoder.