Zlib-stream decompressor for Discord gateway transport compression.
Maintains a persistent inflate context across the lifetime of a gateway
connection, accumulates fragmented frames, and decompresses when the
zlib sync flush suffix (0x00 0x00 0xFF 0xFF) is detected.
Features
- Frame buffering — accumulates fragments until the zlib suffix is detected
- Suffix detection — binary pattern match on the last 4 bytes (no list conversion)
- Error recovery — decompression failures reset the context instead of crashing
- Buffer size limit — prevents unbounded memory growth from malformed streams
- Proper lifecycle — init, reset, close with resource cleanup
- Telemetry — emits events on decompression errors
Usage
{:ok, zlib} = EDA.Gateway.Zlib.init()
case EDA.Gateway.Zlib.push(zlib, binary_frame) do
{:ok, json_binary, zlib} -> # complete message decompressed
{:incomplete, zlib} -> # buffered, waiting for more data
{:error, reason, zlib} -> # decompression error, context was reset
end
zlib = EDA.Gateway.Zlib.reset(zlib) # on reconnect
:ok = EDA.Gateway.Zlib.close(zlib) # on shutdown
Summary
Functions
Closes the zlib context and frees resources.
Creates a new zlib decompressor with a fresh inflate context.
Pushes a binary frame into the decompressor.
Resets the inflate context and clears the buffer.
Types
@type t() :: %EDA.Gateway.Zlib{buffer: binary(), context: :zlib.zstream()}
Functions
@spec close(t()) :: :ok
Closes the zlib context and frees resources.
The struct must not be used after calling this.
@spec init() :: {:ok, t()}
Creates a new zlib decompressor with a fresh inflate context.
Pushes a binary frame into the decompressor.
Returns:
{:ok, decompressed_binary, zlib}— a complete message was decompressed{:incomplete, zlib}— frame buffered, waiting for the zlib suffix{:error, reason, zlib}— decompression failed, context has been reset
Resets the inflate context and clears the buffer.
Call this when reconnecting to the gateway.