Skip to content

feat(decompressor): add Brotli decoder for compression byte 1#125

Closed
infinia-yzl wants to merge 1 commit into
flametime:0.2from
infinia-yzl:upstream-brotli
Closed

feat(decompressor): add Brotli decoder for compression byte 1#125
infinia-yzl wants to merge 1 commit into
flametime:0.2from
infinia-yzl:upstream-brotli

Conversation

@infinia-yzl

Copy link
Copy Markdown

Summary

_decompress_and_parse currently printerrs on wire-format compression byte 1 (Brotli) and drops the payload. SpacetimeDB 2.2 can negotiate Brotli compression (clockworklabs/SpacetimeDB#4561 server-side support). Wire byte 1 to a new DataDecompressor.decompress_brotli_packet that uses Godot's built-in PackedByteArray.decompress_dynamic with FileAccess.COMPRESSION_BROTLI.

Why one-shot, not streaming

Godot ships StreamPeerGZIP but no StreamPeerBrotli, so streaming decoding isn't an option here. The non-streaming decompress_dynamic requires a hard cap on output size — I set BROTLI_MAX_DECOMPRESSED_BYTES = 64 MiB, which comfortably covers any single-frame BSATN payload from a SpacetimeDB server. Larger payloads would already be refused by the WebSocket layer's inbound_buffer_size before reaching here.

Failure mode

Empty PackedByteArray on error — matches the existing decompress_packet contract so _decompress_and_parse callers don't need to change.

Verification

End-to-end via unit tests in a downstream project:

  • Short payload (27 bytes) round-trip via a known Brotli fixture (generated offline since Godot has no Brotli encoder) ✓
  • Highly-redundant 5 KB → 40 bytes Brotli payload round-trip ✓
  • Empty input → empty output ✓
  • Garbage input → empty output, no crash ✓
  • Existing Gzip path unaffected ✓

Test plan

  • Tested against a SpacetimeDB 2.2 server that emits Brotli-compressed payloads
  • Confirm _decompress_and_parse matches case 1 cleanly with the new decoder

Related

🤖 Generated with Claude Code

The wire-format compression byte 1 (Brotli) currently logs
"Brotli compression not supported!" and drops the payload. Wire it
up to Godot's built-in PackedByteArray.decompress_dynamic with
FileAccess.COMPRESSION_BROTLI.

DataDecompressor.decompress_brotli_packet is a one-shot non-streaming
call (Godot has no StreamPeerBrotli equivalent), capped at 64 MiB
output. Larger payloads would already be rejected by the WebSocket
layer's inbound_buffer_size before reaching here.

Failure mode (empty PackedByteArray) matches decompress_packet so the
existing _decompress_and_parse contract is preserved.

Verified end-to-end via unit tests in a downstream project:
short payload round-trip, highly-redundant 5 KB payload round-trip,
empty input → empty output, garbage input → empty + no crash.
Brotli fixtures are generated offline (Godot has no Brotli encoder,
only a decoder).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant