github.com/wasilibs/wazerox@v0.0.0-20240124024944-4923be63ab5f/internal/wasm/binary/value.go (about) 1 package binary 2 3 import ( 4 "bytes" 5 "fmt" 6 "io" 7 "unicode/utf8" 8 "unsafe" 9 10 "github.com/wasilibs/wazerox/internal/leb128" 11 "github.com/wasilibs/wazerox/internal/wasm" 12 ) 13 14 func decodeValueTypes(r *bytes.Reader, num uint32) ([]wasm.ValueType, error) { 15 if num == 0 { 16 return nil, nil 17 } 18 19 ret := make([]wasm.ValueType, num) 20 _, err := io.ReadFull(r, ret) 21 if err != nil { 22 return nil, err 23 } 24 25 for _, v := range ret { 26 switch v { 27 case wasm.ValueTypeI32, wasm.ValueTypeF32, wasm.ValueTypeI64, wasm.ValueTypeF64, 28 wasm.ValueTypeExternref, wasm.ValueTypeFuncref, wasm.ValueTypeV128: 29 default: 30 return nil, fmt.Errorf("invalid value type: %d", v) 31 } 32 } 33 return ret, nil 34 } 35 36 // decodeUTF8 decodes a size prefixed string from the reader, returning it and the count of bytes read. 37 // contextFormat and contextArgs apply an error format when present 38 func decodeUTF8(r *bytes.Reader, contextFormat string, contextArgs ...interface{}) (string, uint32, error) { 39 size, sizeOfSize, err := leb128.DecodeUint32(r) 40 if err != nil { 41 return "", 0, fmt.Errorf("failed to read %s size: %w", fmt.Sprintf(contextFormat, contextArgs...), err) 42 } 43 44 if size == 0 { 45 return "", uint32(sizeOfSize), nil 46 } 47 48 buf := make([]byte, size) 49 if _, err = io.ReadFull(r, buf); err != nil { 50 return "", 0, fmt.Errorf("failed to read %s: %w", fmt.Sprintf(contextFormat, contextArgs...), err) 51 } 52 53 if !utf8.Valid(buf) { 54 return "", 0, fmt.Errorf("%s is not valid UTF-8", fmt.Sprintf(contextFormat, contextArgs...)) 55 } 56 57 // TODO: use unsafe.String after flooring Go 1.20. 58 ret := *(*string)(unsafe.Pointer(&buf)) 59 return ret, size + uint32(sizeOfSize), nil 60 }