github.com/wasilibs/wazerox@v0.0.0-20240124024944-4923be63ab5f/internal/testing/binaryencoding/names.go (about) 1 package binaryencoding 2 3 import ( 4 "github.com/wasilibs/wazerox/internal/leb128" 5 "github.com/wasilibs/wazerox/internal/wasm" 6 ) 7 8 const ( 9 // subsectionIDModuleName contains only the module name. 10 subsectionIDModuleName = uint8(0) 11 // subsectionIDFunctionNames is a map of indices to function names, in ascending order by function index 12 subsectionIDFunctionNames = uint8(1) 13 // subsectionIDLocalNames contain a map of function indices to a map of local indices to their names, in ascending 14 // order by function and local index 15 subsectionIDLocalNames = uint8(2) 16 ) 17 18 // EncodeNameSectionData serializes the data for the "name" key in wasm.SectionIDCustom according to the 19 // standard: 20 // 21 // Note: The result can be nil because this does not encode empty subsections 22 // 23 // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#binary-namesec 24 func EncodeNameSectionData(n *wasm.NameSection) (data []byte) { 25 if n.ModuleName != "" { 26 data = append(data, encodeNameSubsection(subsectionIDModuleName, encodeSizePrefixed([]byte(n.ModuleName)))...) 27 } 28 if fd := encodeFunctionNameData(n); len(fd) > 0 { 29 data = append(data, encodeNameSubsection(subsectionIDFunctionNames, fd)...) 30 } 31 if ld := encodeLocalNameData(n); len(ld) > 0 { 32 data = append(data, encodeNameSubsection(subsectionIDLocalNames, ld)...) 33 } 34 return 35 } 36 37 // encodeFunctionNameData encodes the data for the function name subsection. 38 // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#binary-funcnamesec 39 func encodeFunctionNameData(n *wasm.NameSection) []byte { 40 if len(n.FunctionNames) == 0 { 41 return nil 42 } 43 44 return encodeNameMap(n.FunctionNames) 45 } 46 47 func encodeNameMap(m wasm.NameMap) []byte { 48 count := uint32(len(m)) 49 data := leb128.EncodeUint32(count) 50 for _, na := range m { 51 data = append(data, encodeNameAssoc(na)...) 52 } 53 return data 54 } 55 56 // encodeLocalNameData encodes the data for the local name subsection. 57 // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#binary-localnamesec 58 func encodeLocalNameData(n *wasm.NameSection) []byte { 59 if len(n.LocalNames) == 0 { 60 return nil 61 } 62 63 funcNameCount := uint32(len(n.LocalNames)) 64 subsection := leb128.EncodeUint32(funcNameCount) 65 66 for _, na := range n.LocalNames { 67 locals := encodeNameMap(na.NameMap) 68 subsection = append(subsection, append(leb128.EncodeUint32(na.Index), locals...)...) 69 } 70 return subsection 71 } 72 73 // encodeNameSubsection returns a buffer encoding the given subsection 74 // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#subsections%E2%91%A0 75 func encodeNameSubsection(subsectionID uint8, content []byte) []byte { 76 contentSizeInBytes := leb128.EncodeUint32(uint32(len(content))) 77 result := []byte{subsectionID} 78 result = append(result, contentSizeInBytes...) 79 result = append(result, content...) 80 return result 81 } 82 83 // encodeNameAssoc encodes the index and data prefixed by their size. 84 // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#binary-namemap 85 func encodeNameAssoc(na wasm.NameAssoc) []byte { 86 return append(leb128.EncodeUint32(na.Index), encodeSizePrefixed([]byte(na.Name))...) 87 } 88 89 // encodeSizePrefixed encodes the data prefixed by their size. 90 func encodeSizePrefixed(data []byte) []byte { 91 size := leb128.EncodeUint32(uint32(len(data))) 92 return append(size, data...) 93 }