Files
uopi/pkg/pva/pvdata/bitset.go
T
Martino Ferrari c0f7e662be Testing
2026-06-24 01:39:15 +02:00

76 lines
1.6 KiB
Go

package pvdata
import "io"
// BitSet is a variable-length set of bit indices, encoded on the wire as:
//
// compact-size(n_bytes) + n_bytes of little-endian bits.
//
// Bit 0 of byte 0 is field index 0, bit 1 of byte 0 is field index 1, etc.
// Used in pvData Monitor responses for "changed" and "overrun" masks.
type BitSet struct {
bits []byte
}
// NewBitSet returns an empty BitSet.
func NewBitSet() BitSet { return BitSet{} }
// Set sets bit i in the BitSet.
func (bs *BitSet) Set(i int) {
byteIdx := i / 8
for len(bs.bits) <= byteIdx {
bs.bits = append(bs.bits, 0)
}
bs.bits[byteIdx] |= 1 << (uint(i) % 8)
}
// Has reports whether bit i is set.
func (bs *BitSet) Has(i int) bool {
byteIdx := i / 8
if byteIdx >= len(bs.bits) {
return false
}
return bs.bits[byteIdx]&(1<<(uint(i)%8)) != 0
}
// ReadBitSet reads a BitSet from r.
func ReadBitSet(r io.Reader) (BitSet, error) {
n, err := ReadSize(r)
if err != nil {
return BitSet{}, err
}
if n == 0 {
return BitSet{}, nil
}
buf := make([]byte, n)
if _, err := io.ReadFull(r, buf); err != nil {
return BitSet{}, err
}
return BitSet{bits: buf}, nil
}
// WriteBitSet writes bs to w.
func WriteBitSet(w io.Writer, bs BitSet) error {
if err := WriteSize(w, int64(len(bs.bits))); err != nil {
return err
}
if len(bs.bits) == 0 {
return nil
}
_, err := w.Write(bs.bits)
return err
}
// FieldIndices returns all set bit indices in ascending order.
func (bs *BitSet) FieldIndices() []int {
var out []int
for bi, b := range bs.bits {
for bit := 0; bit < 8; bit++ {
if b&(1<<uint(bit)) != 0 {
out = append(out, bi*8+bit)
}
}
}
return out
}