git ssb

0+

wanderer🌟 / js-primea-hypervisor



Tree: a338912f819bd6fa4333e0c982768e58f6f2219f

Files: a338912f819bd6fa4333e0c982768e58f6f2219f / customTypes.js

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

Built with git-ssb-web