GrindCore.net provides a high-performance, AOT-compatible implementation of the Brotli compression algorithm. It wraps the native Brotli v1.1.0 library (sourced from .NET 9.0) and offers both stream-based and block-based (one-shot) compression and decompression. The implementation supports version dispatching, allowing the library to target specific native versions while maintaining a consistent managed API.
The Brotli subsystem is divided into several layers: managed wrappers for native state (BrotliEncoder, BrotliDecoder), high-level abstractions (BrotliStream, BrotliBlock), and the P/Invoke interop layer.
The following diagram illustrates the relationship between managed classes and the native interop layer.
Brotli System Architecture
Sources: src/Brotli/BrotliStream.cs12-14 src/Brotli/BrotliEncoder.cs11-18 src/Brotli/BrotliDecoder.cs11-13 src/Brotli/BrotliTypes.cs83-142
BrotliStream inherits from CompressionStream and provides the standard .NET stream interface for Brotli.
BufferSizeInput and BufferSizeOutput are set to 65,520 bytes (64KB - 16) src/Brotli/BrotliStream.cs20-25BrotliEncoder to process data during OnWrite. It resolves window bits from CompressionOptions.Dictionary src/Brotli/BrotliStream.cs35-40BrotliDecoder via the internal tryDecompress method during OnRead src/Brotli/BrotliStream.cs54-96.Position (compressed bytes) and .PositionFullSize (uncompressed bytes) through the base class README.md88Sources: src/Brotli/BrotliStream.cs10-44 src/Brotli/BrotliStream.cs109-130
BrotliBlock provides "one-shot" compression and decompression for discrete data blocks without the overhead of a stream.
RequiredCompressOutputSize is calculated as blockSize + (blockSize >> 1) + 16 to ensure the destination buffer can accommodate worst-case Brotli expansion src/Brotli/BrotliBlock.cs46CompressionOptions.Dictionary (defaulting to 22) and clamped between 10 and 24 src/Brotli/BrotliBlock.cs39-44BrotliBlock calls DN9_BRT_v1_1_0_BrotliEncoderCompress and DN9_BRT_v1_1_0_BrotliDecoderDecompress directly src/Brotli/BrotliBlock.cs65-104Sources: src/Brotli/BrotliBlock.cs11-136
The BrotliEncoder is an internal struct that manages the native encoder state via SafeBrotliEncoderHandle.
| Function | Description |
|---|---|
InitializeEncoder | Creates a native instance using DN9_BRT_v1_1_0_BrotliEncoderCreateInstance src/Brotli/BrotliEncoder.cs53-65 |
SetQuality | Sets the compression level (0-11) via BrotliEncoderParameter.Quality src/Brotli/BrotliEncoder.cs103-119 |
SetWindow | Sets the LZ77 sliding window size (10-24) via BrotliEncoderParameter.LGWin src/Brotli/BrotliEncoder.cs136-155 |
EncodeData | Wraps native calls to process input buffers into output buffers src/Brotli/BrotliEncoder.cs181-229 |
Flush | Finalizes the stream or flushes pending bits using BrotliEncoderOperation.Finish or Flush src/Brotli/BrotliEncoder.cs240-286 |
Sources: src/Brotli/BrotliEncoder.cs11-286 src/Brotli/BrotliTypes.cs17-31
BrotliDecoder handles decompression state. It utilizes OperationStatus to communicate with the calling stream/block about the state of the bitstream.
Decompression Data Flow
Sources: src/Brotli/BrotliDecoder.cs83-145 src/Brotli/BrotliTypes.cs57-78
GrindCore supports multiple versions of native libraries. Currently, Brotli is pinned to v1.1.0 (Index 0), sourced from .NET 9.0 README.md74
_state.Version.Index before calling native methods. If an unsupported version index is provided, an exception is thrown src/Brotli/BrotliEncoder.cs36-39 src/Brotli/BrotliDecoder.cs26-29SafeBrotliEncoderHandle and SafeBrotliDecoderHandle ensure that native memory is released via DN9_BRT_v1_1_0_BrotliEncoderDestroyInstance and DN9_BRT_v1_1_0_BrotliDecoderDestroyInstance respectively src/Brotli/BrotliTypes.cs83-142OperationStatus enum:
1 (Success) -> OperationStatus.Done2 (Needs More Input) -> OperationStatus.NeedMoreData3 (Needs More Output) -> OperationStatus.DestinationTooSmall0 (Error) -> OperationStatus.InvalidDataSources: src/Brotli/BrotliDecoder.cs130-142 src/Brotli/BrotliTypes.cs57-78 src/Brotli/BrotliBlock.cs125-135