silk.compress.brotli.
Decompress Brotli data (RFC 7932) in steps, with fixed memory and limits that you set.
When to use#
Use Brotli to read .br files or HTTP bodies with Content-Encoding: br. Make a decoder
with Brotli.make, and call Brotli.step until it returns Finished. Call
Brotli.reset to decode another stream with the same storage. To compress, use
silk.compress.brotli_encode.BrotliEncoder.
Details#
The decoder supports all of RFC 7932: compressed, uncompressed, and metadata meta-blocks, all
context modes, and the static dictionary with its 121 word transforms. Brotli.make allocates
all storage one time: the history window and the space for prefix code tables. Brotli.step
does not allocate and keeps no borrow of your buffers, so you can move the decoder between
threads between calls.
A Brotli stream ends itself. The decoder returns Finished when the last meta-block is decoded
and all output is written, and it leaves the bytes after the stream unconsumed.
Errors#
OutOfMemoryErrorfromBrotli.makeif theAllocatorfails.BrotliErrorif the configuration is not valid, the data is not valid, a limit is exceeded, or a call after the final input does not give exactly the input that is not consumed yet.reasongives the cause andoffsetthe input position.
Gotchas#
The window holds windowBytes rounded down to a power of two. A stream can declare a larger
window than that and still decode, as long as no back-reference reaches further than the window
holds. A failure is permanent until Brotli.reset.
Examples#
Decode a short stream#
import silk.mem.allocator { Allocator, OutOfMemoryError }
import silk.core.effect { Effect }
import silk.core.result { Result }
import silk.compress.brotli { Brotli, BrotliError, BrotliLimits, BrotliProgress, BrotliStatus }
pub effect fn main() -> i32
! BrotliError | OutOfMemoryError {
let mut allocator = Allocator.systemAllocatorProvider()
let mut decoder = run Brotli.make(BrotliLimits.make())
|> Effect.provideMut<Allocator>(&mut allocator)
// The reference encoder's output for "hi": one uncompressed meta-block and an empty last one.
let input = b"\x8b\x00\x80hi\x03"
let mut output: [u8; 16] = [0; 16]
return match Brotli.step(&mut decoder, &input, &mut output, true) {
Result<BrotliProgress, BrotliError>.Success { value } => {
if value.status != BrotliStatus.Finished || value.written != 2 || output[0] != 104
|| output[1] != 105 {
return 1
}
return 0
}
Result<BrotliProgress, BrotliError>.Failure {..} => 1
}
}Import as Brotli with import silk.compress.brotli { Brotli }.
Public declarations: 6.
BrotliLimits#
pub struct BrotliLimitsThe resource limits for one stream. BrotliLimits.make gives defaults.
Field inputBytes#
pub inputBytes: u64The maximum number of input bytes to consume.
Field outputBytes#
pub outputBytes: u64The maximum number of decoded bytes.
Field windowBytes#
pub windowBytes: usizeThe size of the history window that Brotli.make allocates, rounded down to a power of two
and capped at 16 MiB, the largest window of the format. It must not be 0. A back-reference
further than the window fails with WindowLimit.
Field workspaceBytes#
pub workspaceBytes: usizeThe storage budget other than the window: decoder state, context maps, and the space for the
prefix code tables of one meta-block. If it is too small for the fixed part, Brotli.make
fails with WorkspaceLimit, and if a meta-block needs more table space than it leaves, the
step fails with WorkspaceLimit.
Implementation BrotliLimits#
impl BrotliLimitsAssociated function make#
pub fn make() -> SelfReturns default limits: 64 MiB of input, 256 MiB of output, a 16 MiB window, and a 3 MiB workspace. These decode any valid stream within the input and output limits.
BrotliStatus#
pub enum BrotliStatusWhat the decoder needs after a successful step.
NeedInput#
NeedInputAll given input is consumed. Call again with more input, or with finalInput set if there is
no more.
NeedOutput#
NeedOutputThe output buffer is full. Call again with an output buffer that is not empty, and the input that was not consumed.
Finished#
FinishedThe stream is complete and all of its output is written. The bytes after it are not consumed.
BrotliProgress#
pub struct BrotliProgressThe result of one successful step.
Field consumed#
pub consumed: usizeThe number of input bytes that this call consumed. Give only the rest of the input on the next call.
Field written#
pub written: usizeThe number of output bytes that this call wrote. Only this prefix of the output changed.
Field status#
pub status: BrotliStatusWhat the decoder needs next.
BrotliReason#
pub enum BrotliReasonThe cause of a BrotliError.
None#
NoneNo failure. The decoder uses it internally. A returned error never has it.
InvalidConfiguration#
InvalidConfigurationThe window size is 0, or the storage sizes do not fit in usize.
InvalidState#
InvalidStateA call changes the final input after it was set, or uses a decoder that lost its storage.
WindowBits#
WindowBitsThe stream header asks for a window size that RFC 7932 does not define.
Header#
HeaderA meta-block header is not valid: a reserved bit is set, a length has an extra zero nibble or byte, or padding bits are not zero.
PrefixCode#
PrefixCodeA prefix code is not valid: a symbol is out of range or repeated, a code is incomplete or oversubscribed, or a repeat runs past the alphabet.
ContextMap#
ContextMapA context map has a run of zeros past its end.
BlockLength#
BlockLengthThe commands of a meta-block produce more bytes than its length.
Distance#
DistanceA distance is 0 or less, or too large.
Dictionary#
DictionaryA static dictionary reference has a length with no words, or a transform that does not exist.
Truncated#
TruncatedThe final input ends before the stream is complete.
InputLimit#
InputLimitThe consumed input would go over BrotliLimits.inputBytes.
OutputLimit#
OutputLimitThe decoded output would go over BrotliLimits.outputBytes.
WindowLimit#
WindowLimitA back-reference reaches further than the window that Brotli.make allocated.
WorkspaceLimit#
WorkspaceLimitBrotliLimits.workspaceBytes is too small for the decoder state or for the prefix code
tables of a meta-block.
Implementation Debug for BrotliReason#
impl Debug for BrotliReasonOperation debug#
effect fn debug(self: &Self, formatter: &mut Formatter) -> ()
! WriterError
? &mut WriterWrites the name of the variant, such as None.
BrotliError#
pub struct BrotliErrorA decoding failure. It is permanent until Brotli.reset.
Each later call returns the same reason and offset with no progress. The output that earlier
calls wrote is not valid.
Field reason#
pub reason: BrotliReasonThe cause of the failure.
Field offset#
pub offset: u64The input position where the decoder found the problem, counted from the start of the stream.
Field consumed#
pub consumed: usizeThe number of input bytes that this call consumed before it failed.
Field written#
pub written: usizeThe number of output bytes that this call wrote before it failed.
Implementation Debug for BrotliError#
impl Debug for BrotliErrorOperation debug#
effect fn debug(self: &Self, formatter: &mut Formatter) -> ()
! WriterError
? &mut WriterWrites the fields, as BrotliError { reason: ..., offset: ..., ... }.
Brotli#
pub struct BrotliA Brotli decoder for one stream at a time. It owns all its storage.
When to use#
Use it to read .br files or HTTP bodies with Content-Encoding: br. Make a decoder with
Brotli.make, call Brotli.step until it returns Finished, and call Brotli.reset to
decode another stream.
Details#
Brotli.make allocates the window and the table space one time. Brotli.step does not
allocate and keeps no borrow of your buffers, so you can move the decoder between threads
between calls.
Gotchas#
A failure is permanent until Brotli.reset. Output that the stream wrote before a failure is
not valid.
Implementation Brotli#
impl BrotliAssociated function make#
pub effect fn make(limits: BrotliLimits) -> Self
! BrotliError | OutOfMemoryError
? &mut AllocatorReturns a decoder that uses limits, with storage from the ambient Allocator.
It allocates the window and the workspace. Brotli.step does not allocate. Both come from
Allocator.allocateZeroed, so with the system allocator a large window takes memory only as
the stream fills it.
Errors#
BrotliErrorwithWorkspaceLimitifworkspaceBytesis too small for the fixed state, or withInvalidConfigurationifwindowBytesis 0. These checks come before the allocation.OutOfMemoryErrorif theAllocatorfails.
Method reset#
pub fn reset(self: &mut Self) -> ()Starts a new stream with the same limits and storage. It does not allocate. It drops the state of the current stream and a failure.
Method step#
pub fn step(self: &mut Self, input: &[u8], output: &mut [u8], finalInput: bool) -> Result<
BrotliProgress,
BrotliError,
>Decodes from input into output and returns how much it consumed and wrote.
On the next call, give only the input after the consumed prefix, and use only the written
prefix of the output. Set finalInput when input holds all remaining data. After that, each
call must set finalInput and give exactly the input that is not consumed yet. NeedOutput
with an empty output makes no progress. After Finished, each call returns Finished and
consumes nothing.
Errors#
BrotliErrorif the data is not valid, aBrotliLimitsvalue would be exceeded, the final input ends early (Truncated), or the call changes the final input (InvalidState).
Gotchas#
A failure is permanent until Brotli.reset.
Category: Data formats.
Profiles: aarch64-apple-darwin, aarch64-unknown-linux-gnu, aarch64-unknown-linux-gnu-no-libc, x86_64-unknown-linux-gnu, x86_64-unknown-linux-gnu-no-libc, wasm32-unknown-unknown, wasm32-wasip1, wasm32-wasip2, x86_64-pc-windows-msvc, wasm64-unknown-unknown.