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) { if n >= len(data) { return 0, nil, n, ErrWrongBufferLength } tag, nn, err := DecodeI16[uint16](data[n:]) if err != nil { return 0, nil, n, err } n += nn if n >= len(data) { return 0, nil, n, ErrWrongBufferLength } length, nn, err := DecodeGBEU[uint64](data[n:]) if err != nil { return 0, nil, n, err } n += nn end := n + int(length) if end > len(data) { return 0, nil, n, ErrWrongBufferLength } value = data[n:end] 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 }