github.com/protolambda/zssz@v0.1.5/bitfields/bitvector.go (about) 1 package bitfields 2 3 import "fmt" 4 5 // Bitvectors should have a pointer-receiver BitLen function to derive its fixed bit-length from. 6 type BitvectorMeta interface { 7 SizedBits 8 } 9 10 type Bitvector interface { 11 Bitfield 12 BitvectorMeta 13 } 14 15 // Helper function to implement Bitvector with. 16 // It checks if: 17 // 1. b has the same amount of bytes as necessary for n bits. 18 // 2. unused bits in b are 0 19 func BitvectorCheck(b []byte, n uint64) error { 20 byteLen := uint64(len(b)) 21 if err := BitvectorCheckByteLen(byteLen, n); err != nil { 22 return err 23 } 24 if byteLen == 0 { 25 // empty bitvector 26 return nil 27 } 28 last := b[byteLen-1] 29 return BitvectorCheckLastByte(last, n) 30 } 31 32 func BitvectorCheckByteLen(byteLen uint64, bitLength uint64) error { 33 if expected := (bitLength + 7) >> 3; byteLen != expected { 34 return fmt.Errorf("bitvector of %d bytes has not expected length in bytes %d", byteLen, expected) 35 } 36 return nil 37 } 38 39 func BitvectorCheckLastByte(last byte, n uint64) error { 40 if n == 0 { 41 return fmt.Errorf("empty bitvector can not have a last byte") 42 } 43 if n&7 == 0 { 44 // n is a multiple of 8, so last byte fits 45 return nil 46 } 47 // check if it is big enough to hold any non-zero contents in the last byte. 48 if expectedBitsLen := n & 7; (last >> expectedBitsLen) != 0 { 49 return fmt.Errorf("bitvector last byte 0b%b has not expected %d bits in last byte", last, expectedBitsLen) 50 } 51 return nil 52 }