document for BitStorage

This commit is contained in:
Tnze
2021-04-04 11:06:46 +08:00
parent 0344f49f28
commit 45340d4f3a

View File

@ -5,6 +5,8 @@ import (
"math" "math"
) )
// BitStorage implement the compacted data array used in chunk storage.
// https://wiki.vg/Chunk_Format
// This implement the format since Minecraft 1.16 // This implement the format since Minecraft 1.16
type BitStorage struct { type BitStorage struct {
data []uint64 data []uint64
@ -14,7 +16,11 @@ type BitStorage struct {
valuesPerLong int valuesPerLong int
} }
// NewBitStorage create a new BitStorage, // TODO: document // NewBitStorage create a new BitStorage.
// bits is the number of bits per value.
// size is the number of values.
// arrl is optional data for initializing.
// It's length must match the bits and size if it's not nil.
func NewBitStorage(bits, size int, arrl []uint64) (b *BitStorage) { func NewBitStorage(bits, size int, arrl []uint64) (b *BitStorage) {
b = &BitStorage{ b = &BitStorage{
mask: 1<<bits - 1, mask: 1<<bits - 1,
@ -25,7 +31,7 @@ func NewBitStorage(bits, size int, arrl []uint64) (b *BitStorage) {
dataLen := (size + b.valuesPerLong - 1) / b.valuesPerLong dataLen := (size + b.valuesPerLong - 1) / b.valuesPerLong
if arrl != nil { if arrl != nil {
if len(arrl) != dataLen { if len(arrl) != dataLen {
panic(fmt.Errorf("invalid length given for storage, got: %d but expected: %d", len(arrl), dataLen)) panic(initBitStorageErr{ArrlLen: len(arrl), WantLen: dataLen})
} }
b.data = arrl b.data = arrl
} else { } else {
@ -34,11 +40,21 @@ func NewBitStorage(bits, size int, arrl []uint64) (b *BitStorage) {
return return
} }
type initBitStorageErr struct {
ArrlLen int
WantLen int
}
func (i initBitStorageErr) Error() string {
return fmt.Sprintf("invalid length given for storage, got: %d but expected: %d", i.ArrlLen, i.WantLen)
}
func (b *BitStorage) cellIndex(n int) int { func (b *BitStorage) cellIndex(n int) int {
elemPerLong := 64 / b.bits elemPerLong := 64 / b.bits
return n / elemPerLong return n / elemPerLong
} }
// Swap sets v into [i], and return the previous [i] value.
func (b *BitStorage) Swap(i, v int) (old int) { func (b *BitStorage) Swap(i, v int) (old int) {
if i < 0 || i > b.size-1 || if i < 0 || i > b.size-1 ||
v < 0 || uint64(v) > b.mask { v < 0 || uint64(v) > b.mask {
@ -52,6 +68,7 @@ func (b *BitStorage) Swap(i, v int) (old int) {
return return
} }
// Set sets v into [i]
func (b *BitStorage) Set(i, v int) { func (b *BitStorage) Set(i, v int) {
if i < 0 || i > b.size-1 || if i < 0 || i > b.size-1 ||
v < 0 || uint64(v) > b.mask { v < 0 || uint64(v) > b.mask {
@ -63,6 +80,7 @@ func (b *BitStorage) Set(i, v int) {
b.data[c] = l&(b.mask<<offset^math.MaxUint64) | (uint64(v)&b.mask)<<offset b.data[c] = l&(b.mask<<offset^math.MaxUint64) | (uint64(v)&b.mask)<<offset
} }
// Get gets [i] value.
func (b *BitStorage) Get(i int) int { func (b *BitStorage) Get(i int) int {
if i < 0 || i > b.size-1 { if i < 0 || i > b.size-1 {
panic("out of bounds") panic("out of bounds")