71 lines
1.7 KiB
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
|
|
}
|