wa-lang.org/wazero@v1.0.2/internal/wasm/binary/data.go (about) 1 package binary 2 3 import ( 4 "bytes" 5 "fmt" 6 "io" 7 8 "wa-lang.org/wazero/api" 9 "wa-lang.org/wazero/internal/leb128" 10 "wa-lang.org/wazero/internal/wasm" 11 ) 12 13 // dataSegmentPrefix represents three types of data segments. 14 // 15 // https://www.w3.org/TR/2022/WD-wasm-core-2-20220419/binary/modules.html#data-section 16 type dataSegmentPrefix = uint32 17 18 const ( 19 // dataSegmentPrefixActive is the prefix for the version 1.0 compatible data segment, which is classified as "active" in 2.0. 20 dataSegmentPrefixActive dataSegmentPrefix = 0x0 21 // dataSegmentPrefixPassive prefixes the "passive" data segment as in version 2.0 specification. 22 dataSegmentPrefixPassive dataSegmentPrefix = 0x1 23 // dataSegmentPrefixActiveWithMemoryIndex is the active prefix with memory index encoded which is defined for futur use as of 2.0. 24 dataSegmentPrefixActiveWithMemoryIndex dataSegmentPrefix = 0x2 25 ) 26 27 func decodeDataSegment(r *bytes.Reader, enabledFeatures api.CoreFeatures) (*wasm.DataSegment, error) { 28 dataSegmentPrefx, _, err := leb128.DecodeUint32(r) 29 if err != nil { 30 return nil, fmt.Errorf("read data segment prefix: %w", err) 31 } 32 33 if dataSegmentPrefx != dataSegmentPrefixActive { 34 if err := enabledFeatures.RequireEnabled(api.CoreFeatureBulkMemoryOperations); err != nil { 35 return nil, fmt.Errorf("non-zero prefix for data segment is invalid as %w", err) 36 } 37 } 38 39 var expr *wasm.ConstantExpression 40 switch dataSegmentPrefx { 41 case dataSegmentPrefixActive, 42 dataSegmentPrefixActiveWithMemoryIndex: 43 // Active data segment as in 44 // https://www.w3.org/TR/2022/WD-wasm-core-2-20220419/binary/modules.html#data-section 45 if dataSegmentPrefx == 0x2 { 46 d, _, err := leb128.DecodeUint32(r) 47 if err != nil { 48 return nil, fmt.Errorf("read memory index: %v", err) 49 } else if d != 0 { 50 return nil, fmt.Errorf("memory index must be zero but was %d", d) 51 } 52 } 53 54 expr, err = decodeConstantExpression(r, enabledFeatures) 55 if err != nil { 56 return nil, fmt.Errorf("read offset expression: %v", err) 57 } 58 case dataSegmentPrefixPassive: 59 // Passive data segment doesn't need const expr nor memory index encoded. 60 // https://www.w3.org/TR/2022/WD-wasm-core-2-20220419/binary/modules.html#data-section 61 default: 62 return nil, fmt.Errorf("invalid data segment prefix: 0x%x", dataSegmentPrefx) 63 } 64 65 vs, _, err := leb128.DecodeUint32(r) 66 if err != nil { 67 return nil, fmt.Errorf("get the size of vector: %v", err) 68 } 69 70 b := make([]byte, vs) 71 if _, err := io.ReadFull(r, b); err != nil { 72 return nil, fmt.Errorf("read bytes for init: %v", err) 73 } 74 75 return &wasm.DataSegment{ 76 OffsetExpression: expr, 77 Init: b, 78 }, nil 79 } 80 81 func encodeDataSegment(d *wasm.DataSegment) (ret []byte) { 82 // Currently multiple memories are not supported. 83 ret = append(ret, leb128.EncodeInt32(0)...) 84 ret = append(ret, encodeConstantExpression(d.OffsetExpression)...) 85 ret = append(ret, leb128.EncodeUint32(uint32(len(d.Init)))...) 86 ret = append(ret, d.Init...) 87 return 88 }