This is an automated email from the ASF dual-hosted git repository.

zeroshade pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow-go.git


The following commit(s) were added to refs/heads/main by this push:
     new a01f0144 fix(parquet/compress): Brotli CompressBound (#884)
a01f0144 is described below

commit a01f0144bb9df50d547305e3e0081e4737c10d50
Author: Minh Vu <[email protected]>
AuthorDate: Fri Jul 3 20:33:43 2026 +0200

    fix(parquet/compress): Brotli CompressBound (#884)
    
    ### What changed
    
    Brotli `CompressBound` now returns the computed maximum compressed size
    instead of the input length. The empty-input case is also handled before
    the debug assertion so it remains valid with `-tags assert`.
    
    ### Why
    
    The `Codec` contract says callers can use `CompressBound` to allocate a
    destination buffer large enough for compressed output. Returning the
    input length could under-report the bound for Brotli and cause callers
    to allocate too little.
    
    ### Validation
    
    - `go test ./parquet/compress`
    - `go test -tags assert ./parquet/compress`
    - `PARQUET_TEST_DATA=parquet-testing/data
    PARQUET_TEST_BAD_DATA=parquet-testing/bad_data go test ./parquet/...`
---
 parquet/compress/brotli.go        |  8 ++++----
 parquet/compress/compress_test.go | 22 ++++++++++++++++++++++
 2 files changed, 26 insertions(+), 4 deletions(-)

diff --git a/parquet/compress/brotli.go b/parquet/compress/brotli.go
index 82c1f7b0..536ebda8 100644
--- a/parquet/compress/brotli.go
+++ b/parquet/compress/brotli.go
@@ -85,17 +85,17 @@ func (brotliCodec) Decode(dst, src []byte) []byte {
 // BrotliEncoderMaxCompressedSize
 func (brotliCodec) CompressBound(len int64) int64 {
        // [window bits / empty metadata] + N * [uncompressed] + [last empty]
+       if len == 0 {
+               return 2
+       }
        debug.Assert(len > 0, "brotli compressbound should be > 0")
        nlarge := len >> 14
        overhead := 2 + (4 * nlarge) + 3 + 1
        result := len + overhead
-       if len == 0 {
-               return 2
-       }
        if result < len {
                return 0
        }
-       return len
+       return result
 }
 
 func (brotliCodec) NewWriter(w io.Writer) io.WriteCloser {
diff --git a/parquet/compress/compress_test.go 
b/parquet/compress/compress_test.go
index 6b65f23b..019552dd 100644
--- a/parquet/compress/compress_test.go
+++ b/parquet/compress/compress_test.go
@@ -134,6 +134,28 @@ func TestGzipCompressBound(t *testing.T) {
        }
 }
 
+func TestBrotliCompressBound(t *testing.T) {
+       codec, err := compress.GetCodec(compress.Codecs.Brotli)
+       assert.NoError(t, err)
+
+       tests := []struct {
+               name string
+               len  int64
+               want int64
+       }{
+               {"empty", 0, 2},
+               {"small", 1, 7},
+               {"before 16k boundary", 16*1024 - 1, 16*1024 + 5},
+               {"at 16k boundary", 16 * 1024, 16*1024 + 10},
+       }
+
+       for _, tt := range tests {
+               t.Run(tt.name, func(t *testing.T) {
+                       assert.Equal(t, tt.want, codec.CompressBound(tt.len))
+               })
+       }
+}
+
 func TestCompressReaderWriter(t *testing.T) {
        tests := []struct {
                c compress.Compression

Reply via email to