Silk

silk/inflate

Profiles: aarch64-apple-darwin, aarch64-unknown-linux-gnu, aarch64-unknown-linux-gnu-no-libc, wasm32-unknown-unknown, x86_64-unknown-linux-gnu, x86_64-unknown-linux-gnu-no-libc.

Bounded streaming decoding for raw DEFLATE, zlib, and gzip bytes.

When to use

Use Decoder to decode compressed input into caller-owned output buffers. Select Format explicitly. Use make to create state and step to decode bytes. Use reset to reuse a decoder for another independent stream. This module does not detect formats or encode data.

Details

Construction acquires two bounded allocations: history and table storage. Steps and reset retain no borrowed buffers and allocate nothing. Limits count consumed input, emitted output, started members, and header bytes within each independent stream. Raw and zlib stop at the first stream boundary. Gzip accepts concatenated members and requires final input.

Gotchas

Output is provisional until Finished. Discard all output after a decoding failure. Preset dictionaries are unsupported. A failed decoder rejects steps until a successful reset.

Examples

Decode a stored block into a caller-owned buffer

import silk.allocator {Allocator, OutOfMemoryError}
import silk.effect {Effect}
import silk.inflate {Decoder, DecodeError, Format, Limits, Progress, Status}
import silk.result {Result}

effect fn decode() -> i32 ! OutOfMemoryError | DecodeError {
  let mut allocator = Allocator.systemAllocatorProvider()
  let limits = Limits {
    maxInputBytes: 7,
    maxOutputBytes: 2,
    maxMembers: 1,
    maxHeaderBytes: 0,
    maxMemoryBytes: 65536,
  }
  let creating = Decoder.make(Format.Raw, move limits)
    |> Effect.provideMut<Allocator>(&mut allocator)
  let mut decoder = run creating
  let input = b"\x01\x02\x00\xfd\xffhi"
  let mut output: [u8; 2] = [0, 0]
  let result = Decoder.step(&mut decoder, &input, &mut output, true)
  return match move result {
    Result<Progress, DecodeError>.Success {value} => inspect(move value, &output)
    Result<Progress, DecodeError>.Failure {error} => 99
  }
}

fn inspect(progress: Progress, output: &[u8]) -> i32 {
  if progress.status != Status.Finished || progress.consumed != 7 || progress.written != 2 {
    return 1
  }
  if output[0] != 104 || output[1] != 105 {
    return 2
  }
  return 0
}

effect fn recover(error: OutOfMemoryError | DecodeError) -> i32 {
  return 99
}

pub fn main() -> i32 {
  return run Effect.catchAll(decode(), recover)
}

Import as Decoder with import silk.inflate { Decoder }.

Public declarations: 8.

MEMORY_BOUND

pub const MEMORY_BOUND: u64

A conservative byte bound for decoder storage, owned tables, and temporary decoding state.

Details

The bound excludes caller buffers and allocator metadata. A larger allowance does not increase storage.

Format

pub enum Format

The explicit compressed container format.

Raw

Raw = 0

One raw RFC 1951 DEFLATE stream.

Zlib

Zlib = 1

One RFC 1950 zlib stream without a preset dictionary.

Gzip

Gzip = 2

An RFC 1952 gzip stream with one or more concatenated members.

Status

pub enum Status

The next action required after a successful step.

NeedInput

NeedInput = 0

Supply more input after discarding exactly the consumed prefix.

NeedOutput

NeedOutput = 1

Supply another output buffer and resubmit the unconsumed input suffix.

Finished

Finished = 2

The selected container and its integrity checks are complete.

Limits

pub struct Limits

Explicit cumulative resource allowances. Zero permits no units of that resource.

Field maxInputBytes

pub maxInputBytes: u64

The maximum total number of consumed compressed bytes.

Field maxOutputBytes

pub maxOutputBytes: u64

The maximum total number of emitted uncompressed bytes.

Field maxMembers

pub maxMembers: u64

The maximum number of started members. Raw and zlib each count as one member.

Field maxHeaderBytes

pub maxHeaderBytes: u64

The maximum total number of wrapper header bytes, including gzip optional fields and header CRC.

Field maxMemoryBytes

pub maxMemoryBytes: u64

The available decoder storage allowance. It must be at least MEMORY_BOUND.

Progress

pub struct Progress

Exact progress within one call and the next required action.

Field consumed

pub consumed: usize

The input prefix consumed by this call.

Field written

pub written: usize

The output prefix initialized by this call.

Field status

pub status: Status

The next action required from the caller.

ErrorKind

pub enum ErrorKind

A decoding failure category or the resource allowance that was exceeded.

InvalidHeader

InvalidHeader = 0

A wrapper header violates its format.

UnsupportedMethod

UnsupportedMethod = 1

A wrapper requests a compression method other than DEFLATE.

UnsupportedDictionary

UnsupportedDictionary = 2

A zlib header requests an unsupported preset dictionary.

InvalidBlock

InvalidBlock = 3

A block type, stored length, or compressed symbol is invalid.

InvalidHuffman

InvalidHuffman = 4

A Huffman alphabet or code-length repeat is invalid.

InvalidDistance

InvalidDistance = 5

A match refers outside initialized history or the declared window.

TruncatedInput

TruncatedInput = 6

Final input ends before a required field is complete.

ChecksumMismatch

ChecksumMismatch = 7

A header or data checksum does not match.

SizeMismatch

SizeMismatch = 8

A gzip member size does not match its trailer.

InvalidUse

InvalidUse = 9

The decoder failed earlier or the final-input contract was violated.

InputLimit

InputLimit = 10

Consuming the next byte would exceed the input allowance.

OutputLimit

OutputLimit = 11

Emitting the next byte would exceed the output allowance.

MemberLimit

MemberLimit = 12

Starting a member would exceed the member allowance.

HeaderLimit

HeaderLimit = 13

Consuming a header byte would exceed the header allowance.

MemoryLimit

MemoryLimit = 14

Construction or reset cannot fit within the decoder storage allowance.

DecodeError

pub struct DecodeError

A typed failure with exact progress for the failing call.

Gotchas

The written prefix can contain provisional output. Discard the decoded stream after a step failure. A rejected reset leaves the original decoder and its output unchanged.

Field kind

pub kind: ErrorKind

The failure category.

Field consumed

pub consumed: usize

The input prefix consumed before failure in this call.

Field written

pub written: usize

The output prefix initialized before failure in this call.

Decoder

pub struct Decoder

An owned, bounded decoder with no retained input or output borrow.

Details

Drop releases its history and table allocations. A finished decoder returns Finished with zero progress on later calls. A failed decoder rejects later steps with InvalidUse. A successful reset starts another independent stream with the same owned storage.

Associated function Decoder.make

pub effect<'static> fn make(format: Format, limits: Limits) -> Decoder ! OutOfMemoryError | DecodeError ? &mut Allocator

Creates a decoder and acquires bounded history and table storage through the current allocator.

Details

Construction fails with MemoryLimit or MemberLimit before allocation if either allowance is insufficient. Allocation failure is OutOfMemoryError. The first member counts at construction.

Method Decoder.reset

pub fn reset<'life0>(self: &'life0 mut Decoder, format: Format, limits: Limits) -> silk/result.Result<(), silk/inflate.DecodeError>

Starts another independent stream with the existing decoder storage.

When to use

Use after completion, failure, or abandonment to reuse storage without an allocator requirement.

Details

Success replaces the format and limits and restores fresh stream behavior. Reset allocates nothing. The first member counts immediately. Counters and final-input obligations start again for the new stream. The memory allowance must cover MEMORY_BOUND, and the member allowance must be nonzero. These checks occur in that order before mutation. Rejection returns MemoryLimit or MemberLimit with zero progress. A rejected reset leaves the decoder unchanged. An in-progress stream can continue.

Gotchas

Reset does not validate, reclaim, or erase previous output. Output from failed or abandoned streams remains provisional. Reset does not securely erase the decoder storage.

Method Decoder.step

pub fn step<'life0, 'life1, 'life2>(self: &'life0 mut Decoder, input: &'life1 [u8], output: &'life2 mut [u8], finalInput: bool) -> silk/result.Result<silk/inflate.Progress, silk/inflate.DecodeError>

Decodes input into the supplied output buffer and returns exact per-call progress.

Details

Resubmit only the unconsumed input suffix. Once finalInput is true, keep it true and preserve that suffix length. The caller must preserve suffix contents. A later call can provide a new output buffer of any length. Steps allocate nothing and retain no buffer borrow. An empty output returns NeedOutput when emission is required. Raw and zlib leave trailing input unconsumed. Gzip waits for final exhaustion after a complete member.

Gotchas

Output remains provisional until Finished. A failure poisons the decoder; discard all output after failure. Limits are cumulative across calls and gzip members until a successful reset. Checks occur before the excess byte or member is accepted.

On this page