diff --git a/common/buf/buffer.go b/common/buf/buffer.go index 2aa60e6a..04c886a7 100644 --- a/common/buf/buffer.go +++ b/common/buf/buffer.go @@ -244,6 +244,14 @@ func (b *Buffer) Cap() int32 { return int32(len(b.v)) } +// Available returns the available capacity of the buffer content. +func (b *Buffer) Available() int32 { + if b == nil { + return 0 + } + return int32(len(b.v)) - b.end +} + // IsEmpty returns true if the buffer is empty. func (b *Buffer) IsEmpty() bool { return b.Len() == 0 diff --git a/common/buf/multi_buffer.go b/common/buf/multi_buffer.go index f3b17aef..fcac84d7 100644 --- a/common/buf/multi_buffer.go +++ b/common/buf/multi_buffer.go @@ -144,7 +144,7 @@ func Compact(mb MultiBuffer) MultiBuffer { for i := 1; i < len(mb); i++ { curr := mb[i] - if last.Len()+curr.Len() > Size { + if curr.Len() > last.Available() { mb2 = append(mb2, last) last = curr } else { diff --git a/common/buf/multi_buffer_test.go b/common/buf/multi_buffer_test.go index 2b83a548..40dbdd63 100644 --- a/common/buf/multi_buffer_test.go +++ b/common/buf/multi_buffer_test.go @@ -175,6 +175,29 @@ func TestCompact(t *testing.T) { } } +func TestCompactWithConsumed(t *testing.T) { + // make a consumed buffer (a.Start != 0) + a := New() + for range 8192 { + common.Must2(a.WriteString("a")) + } + a.Read(make([]byte, 2)) + + b := New() + for range 2 { + common.Must2(b.WriteString("b")) + } + + mb := MultiBuffer{a, b} + cmb := Compact(mb) + mbc := &MultiBufferContainer{mb} + mbc.Read(make([]byte, 8190)) + + if w := cmb.String(); w != "bb" { + t.Error("unexpected Compact result ", w) + } +} + func BenchmarkSplitBytes(b *testing.B) { var mb MultiBuffer raw := make([]byte, Size)