func (r *BitReader) Pool() error {
	err := r.Close()
	if err != nil {
		return errors.Wrap(err, "failed to close BitReader before pooling")
	}
	if len(*r.buffer) == smallBuffer {
		smallBufferPool.Put(r.buffer)
	}
	r.buffer = nil
	bitReaderPool.Put(r)
	return nil
}
Pool puts the BitReader into a pool for future use.
Pooling BitReaders improves performance by minimizing the amount newly allocated readers.
package bitread
import (
	"io"
	"math"
	"sync"
	bitread "github.com/markus-wa/gobitread"
	"github.com/pkg/errors"
)
const (
	smallBuffer      = 512
	largeBuffer      = 1024 * 128
	maxVarInt32Bytes = 5
)
type BitReader struct {
	bitread.BitReader
	buffer *[]byte
}
func (r *BitReader) ReadString() string {
	const valveMaxStringLength = 4096
	return r.readStringLimited(valveMaxStringLength, false)
}
func (r *BitReader) readStringLimited(limit int, endOnNewLine bool) string {
	const minStringBufferLength = 256
	result := make([]byte, 0, minStringBufferLength)
	for i := 0; i < limit; i++ {
		b := r.ReadSingleByte()
		if b == 0 || (endOnNewLine && b == '\n') {
			break
		}
		result = append(result, b)
	}
	return string(result)
}
func (r *BitReader) ReadFloat() float32 {
	return math.Float32frombits(uint32(r.ReadInt(32)))
}
func (r *BitReader) ReadVarInt32() uint32 {
	var (
		res uint32
		b   uint32 = 0x80
	)
	for count := uint(0); b&0x80 != 0 && count != maxVarInt32Bytes; count++ {
		b = uint32(r.ReadSingleByte())
		res |= (b & 0x7f) << (7 * count)
	}
	return res
}
func (r *BitReader) ReadSignedVarInt32() int32 {
	res := r.ReadVarInt32()
	return int32((res >> 1) ^ -(res & 1))
}
func (r *BitReader) ReadUBitInt() uint {
	res := r.ReadInt(6)
	switch res & (16 | 32) {
	case 16:
		res = (res & 15) | (r.ReadInt(4) << 4)
	case 32:
		res = (res & 15) | (r.ReadInt(8) << 4)
	case 48:
		res = (res & 15) | (r.ReadInt(32-4) << 4)
	}
	return res
}
var bitReaderPool = sync.Pool{
	New: func() interface{} {
		return new(BitReader)
	},
}