hopp/tape/table.go

71 lines
1.7 KiB
Go

package tape
import "iter"
// encoding and decoding functions must not make any allocations
type TablePushFunc func(tag uint16, value []byte) (n int, err error)
type TablePullFunc func() (tag uint16, value []byte, n int, err error)
func DecodeTable(data []byte) TablePullFunc {
n := 0
return func() (tag uint16, value []byte, n_ int, err error) {
tag, nn, err := DecodeI16[uint16](data[n:])
if err != nil { return tag, value, n, err }
n += nn
length, nn, err := DecodeGBEU[uint64](data[n:])
if err != nil { return tag, value, n, err }
n += nn
value = data[n:n + int(length)]
n += int(length)
return tag, value, n, err
}
}
func DecodeTableIter(data []byte) iter.Seq2[uint16, []byte] {
return func(yield func(uint16, []byte) bool) {
pull := DecodeTable(data)
for {
tag, value, _, err := pull()
if err != nil { return }
if !yield(tag, value) { return }
}
}
}
func EncodeTable(data []byte) TablePushFunc {
return func(tag uint16, value []byte) (n int, err error) {
if n >= len(data) { return n, ErrWrongBufferLength }
nn, err := EncodeI16(data[n:], uint16(tag))
if err != nil { return n, err }
n += nn
if n >= len(data) { return n, ErrWrongBufferLength }
nn, err = EncodeGBEU(data[n:], uint(len(value)))
if err != nil { return n, err }
n += nn
if n >= len(data) { return n, ErrWrongBufferLength }
nn = copy(data[n:], value)
n += nn
if nn < len(value) {
return n, ErrWrongBufferLength
}
if n >= len(data) { return n, ErrWrongBufferLength }
data = data[n:]
return n, nil
}
}
func TableSize(itemLengths ...int) int {
sum := 0
for _, length := range itemLengths {
sum += GBEUSize(uint(length)) + length
}
return sum
}