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<