mirror of
https://gitlab.com/pulsechaincom/prysm-pulse.git
synced 2024-12-22 03:30:35 +00:00
1e3a55c6a6
* Refactor bytes.go and bytes_test.go to smaller files, introduce go1.17 and go1.20 style of array copy * rename bytes_go17.go to reflect that it works on any version 1.19 and below * fix PadTo when len is exactly the size * Add go1.20 style conversions * Forgot another int method Co-authored-by: Radosław Kapka <rkapka@wp.pl> Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
91 lines
1.8 KiB
Go
91 lines
1.8 KiB
Go
package bytesutil
|
|
|
|
import (
|
|
"math/bits"
|
|
|
|
"github.com/pkg/errors"
|
|
)
|
|
|
|
// SetBit sets the index `i` of bitlist `b` to 1.
|
|
// It grows and returns a longer bitlist with 1 set
|
|
// if index `i` is out of range.
|
|
func SetBit(b []byte, i int) []byte {
|
|
if i >= len(b)*8 {
|
|
h := (i + (8 - i%8)) / 8
|
|
b = append(b, make([]byte, h-len(b))...)
|
|
}
|
|
|
|
bit := uint8(1 << (i % 8))
|
|
b[i/8] |= bit
|
|
return b
|
|
}
|
|
|
|
// ClearBit clears the index `i` of bitlist `b`.
|
|
// Returns the original bitlist if the index `i`
|
|
// is out of range.
|
|
func ClearBit(b []byte, i int) []byte {
|
|
if i >= len(b)*8 || i < 0 {
|
|
return b
|
|
}
|
|
|
|
bit := uint8(1 << (i % 8))
|
|
b[i/8] &^= bit
|
|
return b
|
|
}
|
|
|
|
// MakeEmptyBitlists returns an empty bitlist with
|
|
// input size `i`.
|
|
func MakeEmptyBitlists(i int) []byte {
|
|
return make([]byte, (i+(8-i%8))/8)
|
|
}
|
|
|
|
// HighestBitIndex returns the index of the highest
|
|
// bit set from bitlist `b`.
|
|
func HighestBitIndex(b []byte) (int, error) {
|
|
if len(b) == 0 {
|
|
return 0, errors.New("input list can't be empty or nil")
|
|
}
|
|
|
|
for i := len(b) - 1; i >= 0; i-- {
|
|
if b[i] == 0 {
|
|
continue
|
|
}
|
|
return bits.Len8(b[i]) + (i * 8), nil
|
|
}
|
|
|
|
return 0, nil
|
|
}
|
|
|
|
// HighestBitIndexAt returns the index of the highest
|
|
// bit set from bitlist `b` that is at `index` (inclusive).
|
|
func HighestBitIndexAt(b []byte, index int) (int, error) {
|
|
bLength := len(b)
|
|
if b == nil || bLength == 0 {
|
|
return 0, errors.New("input list can't be empty or nil")
|
|
}
|
|
if index < 0 {
|
|
return 0, errors.Errorf("index is negative: %d", index)
|
|
}
|
|
|
|
start := index / 8
|
|
if start >= bLength {
|
|
start = bLength - 1
|
|
}
|
|
|
|
mask := byte(1<<(index%8) - 1)
|
|
for i := start; i >= 0; i-- {
|
|
if index/8 > i {
|
|
mask = 0xff
|
|
}
|
|
masked := b[i] & mask
|
|
minBitsMasked := bits.Len8(masked)
|
|
if b[i] == 0 || (minBitsMasked == 0 && index/8 <= i) {
|
|
continue
|
|
}
|
|
|
|
return minBitsMasked + (i * 8), nil
|
|
}
|
|
|
|
return 0, nil
|
|
}
|