func (b *Buckets) getBits(offset, length uint) uint32 {
	byteIndex := offset / 8
	byteOffset := offset % 8
	if byteOffset+length > 8 {
		rem := 8 - byteOffset
		return b.getBits(offset, rem) | (b.getBits(offset+rem, length-rem) << rem)
	}
	bitMask := uint32((1 << length) - 1)
	return (uint32(b.data[byteIndex]) & (bitMask << byteOffset)) >> byteOffset
}
getBits returns the bits at the specified offset and length.
package boom
import (
	"bytes"
	"encoding/binary"
	"io"
)
type Buckets struct {
	data       []byte
	bucketSize uint8
	max        uint8
	count      uint
}
func NewBuckets(count uint, bucketSize uint8) *Buckets {
	return &Buckets{
		count:      count,
		data:       make([]byte, (count*uint(bucketSize)+7)/8),
		bucketSize: bucketSize,
		max:        (1 << bucketSize) - 1,
	}
}
func (b *Buckets) MaxBucketValue() uint8 {
	return b.max
}
func (b *Buckets) Count() uint {
	return b.count
}
func (b *Buckets) Increment(bucket uint, delta int32) *Buckets {
	val := int32(b.getBits(bucket*uint(b.bucketSize), uint(b.bucketSize))) + delta
	if val > int32(b.max) {
		val = int32(b.max)
	} else if val < 0 {
		val = 0
	}
	b.setBits(uint32(bucket)*uint32(b.bucketSize), uint32(b.bucketSize), uint32(val))
	return b
}
func (b *Buckets) Set(bucket uint, value uint8) *Buckets {
	if value > b.max {
		value = b.max
	}
	b.setBits(uint32(bucket)*uint32(b.bucketSize), uint32(b.bucketSize), uint32(value))
	return b
}
func (b *Buckets) Get(bucket uint) uint32 {
	return b.getBits(bucket*uint(b.bucketSize), uint(b.bucketSize))
}
func (b *Buckets) Reset() *Buckets {
	b.data = make([]byte, (b.count*uint(b.bucketSize)+7)/8)
	return b
}