diff --git a/bitmap_opt.go b/bitmap_opt.go index a36431c..91188aa 100644 --- a/bitmap_opt.go +++ b/bitmap_opt.go @@ -666,3 +666,17 @@ func (dst *Bitmap) CompareNumKeys(src *Bitmap) int { return 0 } } + +func (ra *Bitmap) LenInBytes() int { + if ra == nil { + return 0 + } + return len(ra.data) * 2 +} + +func (ra *Bitmap) capInBytes() int { + if ra == nil { + return 0 + } + return cap(ra.data) * 2 +} diff --git a/bitmap_opt_test.go b/bitmap_opt_test.go index aa5c569..7bb2555 100644 --- a/bitmap_opt_test.go +++ b/bitmap_opt_test.go @@ -924,6 +924,59 @@ func TestCompareNumKeys(t *testing.T) { }) } +func TestLenBytes(t *testing.T) { + t.Run("non-nil bitmap", func(t *testing.T) { + bm := NewBitmap() + + for _, x := range []int{1, 1 + maxCardinality, 1 + maxCardinality*2} { + bm.Set(uint64(x)) + + require.Equal(t, len(bm.ToBuffer()), bm.LenInBytes()) + } + }) + + t.Run("empty bitmap", func(t *testing.T) { + bm := NewBitmap() + + // real length is greater then 0, though ToBuffer() returns empty slice + require.Less(t, 0, bm.LenInBytes()) + }) + + t.Run("nil bitmap", func(t *testing.T) { + var bm *Bitmap + + require.Equal(t, 0, bm.LenInBytes()) + }) +} + +func TestCapBytes(t *testing.T) { + t.Run("non-nil bitmap", func(t *testing.T) { + bm := NewBitmap() + + for _, x := range []int{1, 1 + maxCardinality, 1 + maxCardinality*2} { + bm.Set(uint64(x)) + + // ToBuffer() sets cap to len, real cap is >= than buffer's one + require.LessOrEqual(t, cap(bm.ToBuffer()), bm.capInBytes()) + require.LessOrEqual(t, bm.LenInBytes(), bm.capInBytes()) + } + }) + + t.Run("empty bitmap", func(t *testing.T) { + bm := NewBitmap() + + // real cap is greater than 0, though ToBuffer() returns empty slice + require.Less(t, 0, bm.capInBytes()) + require.LessOrEqual(t, bm.LenInBytes(), bm.capInBytes()) + }) + + t.Run("nil bitmap", func(t *testing.T) { + var bm *Bitmap + + require.Equal(t, 0, bm.capInBytes()) + }) +} + func TestMergeToSuperset(t *testing.T) { run := func(t *testing.T, bufs [][]uint16) { containerThreshold := uint64(math.MaxUint16 + 1)