git ssb

0+

wanderer🌟 / js-primea-hypervisor



Tree: 21960d62467278cd5659e2eb5f80cc6ddd87e663

Files: 21960d62467278cd5659e2eb5f80cc6ddd87e663 / customTypes.js

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

Built with git-ssb-web