git ssb

0+

wanderer🌟 / js-primea-hypervisor



Tree: b9cefb81b38fc031f3179fbfff55dfd7fa8596a6

Files: b9cefb81b38fc031f3179fbfff55dfd7fa8596a6 / customTypes.js

4862 bytesRaw
1const Stream = require('buffer-pipe')
2const leb = require('leb128')
3const {findSections} = require('wasm-json-toolkit')
4
5const LANGUAGE_TYPES = {
6 'actor': 0x0,
7 'buf': 0x1,
8 'i32': 0x7f,
9 'i64': 0x7e,
10 'f32': 0x7d,
11 'f64': 0x7c,
12 'anyFunc': 0x70,
13 'func': 0x60,
14 'block_type': 0x40,
15
16 0x0: 'actor',
17 0x1: 'buf',
18 0x7f: 'i32',
19 0x7e: 'i64',
20 0x7d: 'f32',
21 0x7c: 'f64',
22 0x70: 'anyFunc',
23 0x60: 'func',
24 0x40: 'block_type'
25}
26
27function encodeJSON (json) {
28 const stream = new Stream()
29 encodeCustomSection('type', json, stream, encodeType)
30 encodeCustomSection('typeMap', json, stream, encodeTypeMap)
31
32 return stream.buffer
33}
34
35function encodeCustomSection (name, json, stream, encodingFunc) {
36 stream.write([0])
37 let payload = new Stream()
38
39 // encode type
40 leb.unsigned.write(name.length, payload)
41 payload.write(name)
42 encodingFunc(json[name], payload)
43 // write the size of the payload
44 leb.unsigned.write(payload.bytesWrote, stream)
45 stream.write(payload.buffer)
46 return stream
47}
48
49function encodeTypeMap (json, stream) {
50 leb.unsigned.write(json.length, stream)
51 for (let entry of json) {
52 leb.unsigned.write(entry.func, stream)
53 leb.unsigned.write(entry.type, stream)
54 }
55 return stream
56}
57
58function decodeTypeMap (buf) {
59 const stream = new Stream(Buffer.from(buf))
60 let numOfEntries = leb.unsigned.read(stream)
61 const json = []
62 while (numOfEntries--) {
63 json.push({
64 func: leb.unsigned.readBn(stream).toNumber(),
65 type: leb.unsigned.readBn(stream).toNumber()
66 })
67 }
68 return json
69}
70
71function encodeType (json, stream = new Stream()) {
72 let binEntries = new Stream()
73
74 leb.unsigned.write(json.length, binEntries)
75 for (let entry of json) {
76 // a single type entry binary encoded
77 binEntries.write([LANGUAGE_TYPES[entry.form]]) // the form
78
79 const len = entry.params.length // number of parameters
80 leb.unsigned.write(len, binEntries)
81 if (len !== 0) {
82 binEntries.write(entry.params.map(type => LANGUAGE_TYPES[type])) // the paramter types
83 }
84
85 binEntries.write([entry.return_type ? 1 : 0]) // number of return types
86
87 if (entry.return_type) {
88 binEntries.write([LANGUAGE_TYPES[entry.return_type]])
89 }
90 }
91
92 stream.write(binEntries.buffer)
93 return stream
94}
95
96function decodeType (buf) {
97 const stream = new Stream(Buffer.from(buf))
98 const numberOfEntries = leb.unsigned.readBn(stream).toNumber()
99 const json = []
100 for (let i = 0; i < numberOfEntries; i++) {
101 let type = stream.read(1)[0]
102 const entry = {
103 form: LANGUAGE_TYPES[type],
104 params: []
105 }
106
107 let paramCount = leb.unsigned.readBn(stream).toNumber()
108
109 // parse the entries
110 while (paramCount--) {
111 const type = stream.read(1)[0]
112 entry.params.push(LANGUAGE_TYPES[type])
113 }
114 const numOfReturns = leb.unsigned.readBn(stream).toNumber()
115 if (numOfReturns) {
116 type = stream.read(1)[0]
117 entry.return_type = LANGUAGE_TYPES[type]
118 }
119
120 json.push(entry)
121 }
122 return json
123}
124
125function injectCustomSection (custom, wasm) {
126 const preramble = wasm.subarray(0, 8)
127 const body = wasm.subarray(8)
128 return Buffer.concat([preramble, custom, body])
129}
130
131function inject (wasm, json) {
132 const buf = encodeJSON(json)
133 return injectCustomSection(buf, wasm)
134}
135
136function mergeTypeSections (json) {
137 const result = {
138 types: [],
139 indexes: {},
140 exports: {}
141 }
142
143 const wantedSections = ['custom', 'custom', 'type', 'import', 'function', 'export']
144 const iterator = findSections(json, wantedSections)
145 const mappedFuncs = new Map()
146 const mappedTypes = new Map()
147 const {value: customType} = iterator.next('custom')
148 if (customType) {
149 const type = decodeType(customType.payload)
150 result.types = type
151 }
152 let {value: typeMap} = iterator.next('custom')
153 if (typeMap) {
154 decodeTypeMap(typeMap.payload).forEach(map => mappedFuncs.set(map.func, map.type))
155 }
156
157 const {value: type} = iterator.next('type')
158 const {value: imports = {entries: []}} = iterator.next('import')
159 const {value: functions} = iterator.next('function')
160 functions.entries.forEach((typeIndex, funcIndex) => {
161 let customIndex = mappedFuncs.get(funcIndex)
162 if (customIndex === undefined) {
163 customIndex = mappedTypes.get(typeIndex)
164 }
165 if (customIndex === undefined) {
166 customIndex = result.types.push(type.entries[typeIndex]) - 1
167 mappedTypes.set(typeIndex, customIndex)
168 }
169 result.indexes[funcIndex + imports.entries.length] = customIndex
170 })
171
172 const {value: exports = {entries: []}} = iterator.next('export')
173 exports.entries.forEach(entry => {
174 if (entry.kind === 'function') {
175 result.exports[entry.field_str] = entry.index
176 }
177 })
178 return result
179}
180
181module.exports = {
182 injectCustomSection,
183 inject,
184 decodeType,
185 decodeTypeMap,
186 encodeType,
187 encodeTypeMap,
188 encodeJSON,
189 mergeTypeSections
190}
191

Built with git-ssb-web