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