tape: Implement PASTA and VILA encoding/decoding
This commit is contained in:
parent
23c3efa845
commit
2b3a53052f
@ -6,23 +6,90 @@ import "slices"
|
|||||||
|
|
||||||
// encoding and decoding functions must not make any allocations
|
// encoding and decoding functions must not make any allocations
|
||||||
|
|
||||||
func DecodeArray(data []byte, itemLength int) iter.Seq[[]byte] {
|
// ArrayPushFunc adds an item to an array that is being encoded.
|
||||||
|
type ArrayPushFunc func(value []byte) (n int, err error)
|
||||||
|
|
||||||
|
// ArrayPullFunc gets the next item of an array that is being decoded.
|
||||||
|
type ArrayPullFunc func() (value []byte, n int, err error)
|
||||||
|
|
||||||
|
// DecodePASTA decodes a packed single-type array.
|
||||||
|
func DecodePASTA(data []byte, itemLength int) ArrayPullFunc {
|
||||||
|
n := 0
|
||||||
|
return func() (value []byte, n_ int, err error) {
|
||||||
|
if n > len(data) - itemLength {
|
||||||
|
return nil, 0, fmt.Errorf("decoding PASTA: %w", ErrWrongBufferLength)
|
||||||
|
}
|
||||||
|
value = data[n:n + itemLength]
|
||||||
|
n += itemLength
|
||||||
|
return value, itemLength, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// DecodePASTAIter decodes a packed single-type array and returns it as an
|
||||||
|
// iterator.
|
||||||
|
func DecodePASTAIter(data []byte, itemLength int) iter.Seq[[]byte] {
|
||||||
return slices.Chunk(data, itemLength)
|
return slices.Chunk(data, itemLength)
|
||||||
}
|
}
|
||||||
|
|
||||||
func EncodeArray(data []byte, items ...[]byte) (n int, err error) {
|
// EncodePASTA encodes a packed single-type array.
|
||||||
for _, item := range items {
|
func EncodePASTA(data []byte, itemLength int) ArrayPushFunc {
|
||||||
if n >= len(data) { return n, ErrWrongBufferLength }
|
n := 0
|
||||||
copy(data[n:], item)
|
return func(value []byte) (n_ int, err error) {
|
||||||
n += len(item)
|
if n > len(data) - itemLength {
|
||||||
|
return 0, fmt.Errorf("encoding PASTA: %w", ErrWrongBufferLength)
|
||||||
|
}
|
||||||
|
copy(data[n:], value)
|
||||||
|
n += itemLength
|
||||||
|
return itemLength, nil
|
||||||
}
|
}
|
||||||
return n, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func ArraySize(length, itemLength int) int {
|
// PASTASize returns the size of a packed single-type array.
|
||||||
|
func PASTASize(length, itemLength int) int {
|
||||||
return length * itemLength
|
return length * itemLength
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DecodeVILA encodes a variable item length array.
|
||||||
|
func DecodeVILA(data []byte) ArrayPullFunc {
|
||||||
|
n := 0
|
||||||
|
return func() (value []byte, n_ int, err error) {
|
||||||
|
if n >= len(data) { return nil, n_, fmt.Errorf("decoding VILA: %w", ErrWrongBufferLength) }
|
||||||
|
length, nn, err := DecodeGBEU[uint](data[n:])
|
||||||
|
n += nn
|
||||||
|
n_ += nn
|
||||||
|
if err != nil { return nil, n_, err }
|
||||||
|
|
||||||
|
if n > len(data) - int(length) {
|
||||||
|
return nil, n_, fmt.Errorf("decoding VILA: %w", ErrWrongBufferLength)
|
||||||
|
}
|
||||||
|
value = data[n:n + int(length)]
|
||||||
|
n += int(length)
|
||||||
|
n_ += int(length)
|
||||||
|
return value, int(length), nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// EncodeVILA encodes a variable item length array.
|
||||||
|
func EncodeVILA(data []byte, items ...[]byte) ArrayPushFunc {
|
||||||
|
n := 0
|
||||||
|
return func(value []byte) (n_ int, err error) {
|
||||||
|
if n >= len(data) { return n_, fmt.Errorf("encoding VILA: %w", ErrWrongBufferLength) }
|
||||||
|
nn, err := EncodeGBEU(data[n:], uint(len(value)))
|
||||||
|
n += nn
|
||||||
|
n_ += nn
|
||||||
|
if err != nil { return n, err }
|
||||||
|
|
||||||
|
if n >= len(data) { return n_, fmt.Errorf("encoding VILA: %w", ErrWrongBufferLength) }
|
||||||
|
nn = copy(data[n:], value)
|
||||||
|
n += nn
|
||||||
|
n_ += nn
|
||||||
|
if nn != len(value) { return n_, fmt.Errorf("encoding VILA: %w", ErrWrongBufferLength) }
|
||||||
|
return n_, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Decode, encode, size for string array needs to use VILA
|
||||||
|
|
||||||
// DecodeStringArray decodes a packed string array from the given data.
|
// DecodeStringArray decodes a packed string array from the given data.
|
||||||
func DecodeStringArray[T String](data []byte) (result []T, n int, err error) {
|
func DecodeStringArray[T String](data []byte) (result []T, n int, err error) {
|
||||||
for len(data) > 0 {
|
for len(data) > 0 {
|
||||||
|
Loading…
Reference in New Issue
Block a user