Files
mstore/vendor/github.com/tetratelabs/wabin/binary/data.go
T
2026-03-13 19:02:42 +02:00

95 lines
3.0 KiB
Go

package binary
import (
"bytes"
"fmt"
"io"
"github.com/tetratelabs/wabin/leb128"
"github.com/tetratelabs/wabin/wasm"
)
// dataSegmentPrefix represents three types of data segments.
//
// https://www.w3.org/TR/2022/WD-wasm-core-2-20220419/binary/modules.html#data-section
type dataSegmentPrefix = uint32
const (
// dataSegmentPrefixActive is the prefix for the version 1.0 compatible
// data segment, which is classified as "active" in 2.0.
dataSegmentPrefixActive dataSegmentPrefix = 0x0
// dataSegmentPrefixPassive prefixes the "passive" data segment as in
// version 2.0 specification.
dataSegmentPrefixPassive dataSegmentPrefix = 0x1
// dataSegmentPrefixActiveWithMemoryIndex is the active prefix with memory
//index encoded which is defined for future use as of 2.0.
dataSegmentPrefixActiveWithMemoryIndex dataSegmentPrefix = 0x2
)
func decodeDataSegment(r *bytes.Reader, features wasm.CoreFeatures) (*wasm.DataSegment, error) {
dataSegmentPrefix, _, err := leb128.DecodeUint32(r)
if err != nil {
return nil, fmt.Errorf("read data segment prefix: %w", err)
}
if dataSegmentPrefix != dataSegmentPrefixActive {
if err := features.RequireEnabled(wasm.CoreFeatureBulkMemoryOperations); err != nil {
return nil, fmt.Errorf("non-zero prefix for data segment is invalid as %w", err)
}
}
var expr *wasm.ConstantExpression
switch dataSegmentPrefix {
case dataSegmentPrefixActive,
dataSegmentPrefixActiveWithMemoryIndex:
// Active data segment as in
// https://www.w3.org/TR/2022/WD-wasm-core-2-20220419/binary/modules.html#data-section
if dataSegmentPrefix == 0x2 {
d, _, err := leb128.DecodeUint32(r)
if err != nil {
return nil, fmt.Errorf("read memory index: %v", err)
} else if d != 0 {
return nil, fmt.Errorf("memory index must be zero but was %d", d)
}
}
expr, err = decodeConstantExpression(r, features)
if err != nil {
return nil, fmt.Errorf("read offset expression: %v", err)
}
case dataSegmentPrefixPassive:
// Passive data segment doesn't need const expr nor memory index encoded.
// https://www.w3.org/TR/2022/WD-wasm-core-2-20220419/binary/modules.html#data-section
default:
return nil, fmt.Errorf("invalid data segment prefix: 0x%x", dataSegmentPrefix)
}
vs, _, err := leb128.DecodeUint32(r)
if err != nil {
return nil, fmt.Errorf("get the size of vector: %v", err)
}
b := make([]byte, vs)
if _, err := io.ReadFull(r, b); err != nil {
return nil, fmt.Errorf("read bytes for init: %v", err)
}
return &wasm.DataSegment{
OffsetExpression: expr,
Init: b,
}, nil
}
func encodeDataSegment(d *wasm.DataSegment) (ret []byte) {
if d.OffsetExpression == nil {
ret = append(ret, leb128.EncodeInt32(int32(dataSegmentPrefixPassive))...)
} else {
// Currently multiple memories are not supported.
ret = append(ret, leb128.EncodeInt32(int32(dataSegmentPrefixActive))...)
ret = append(ret, encodeConstantExpression(d.OffsetExpression)...)
}
ret = append(ret, leb128.EncodeUint32(uint32(len(d.Init)))...)
ret = append(ret, d.Init...)
return
}