goscript 0.2.4 → 0.2.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (117) hide show
  1. package/README.md +8 -8
  2. package/cmd/go_js_wasm_exec/main.go +1 -1
  3. package/cmd/go_js_wasm_exec/main_test.go +1 -1
  4. package/cmd/goscript/cmd-compile.go +9 -1
  5. package/cmd/goscript/cmd-test.go +1 -1
  6. package/cmd/goscript/cmd_compile_test.go +44 -0
  7. package/cmd/goscript/deps.go +1 -1
  8. package/cmd/goscript-wasm/main.go +2 -2
  9. package/compiler/compile-request.go +19 -0
  10. package/compiler/compile_bench_test.go +121 -0
  11. package/compiler/compliance_test.go +17 -1
  12. package/compiler/config.go +2 -0
  13. package/compiler/gotest/result.go +1 -1
  14. package/compiler/gotest/runner.go +2 -2
  15. package/compiler/gotest/runner_test.go +4 -7
  16. package/compiler/index.test.ts +28 -0
  17. package/compiler/index.ts +32 -16
  18. package/compiler/lowering.go +1238 -194
  19. package/compiler/lowering_bench_test.go +4 -0
  20. package/compiler/override-facts.go +1 -1
  21. package/compiler/package-graph.go +92 -0
  22. package/compiler/package-graph_test.go +113 -0
  23. package/compiler/runtime-contract.go +1 -1
  24. package/compiler/semantic-model.go +32 -0
  25. package/compiler/skeleton_test.go +241 -15
  26. package/compiler/wasm/compile.go +1 -1
  27. package/compiler/wasm/compile_test.go +1 -1
  28. package/dist/compiler/index.d.ts +4 -0
  29. package/dist/compiler/index.js +26 -15
  30. package/dist/compiler/index.js.map +1 -1
  31. package/dist/gs/database/sql/driver/index.d.ts +165 -0
  32. package/dist/gs/database/sql/driver/index.js +432 -0
  33. package/dist/gs/database/sql/driver/index.js.map +1 -0
  34. package/dist/gs/encoding/binary/index.d.ts +71 -0
  35. package/dist/gs/encoding/binary/index.js +778 -0
  36. package/dist/gs/encoding/binary/index.js.map +1 -0
  37. package/dist/gs/fmt/fmt.js +156 -57
  38. package/dist/gs/fmt/fmt.js.map +1 -1
  39. package/dist/gs/github.com/klauspost/cpuid/v2/index.d.ts +11 -0
  40. package/dist/gs/github.com/klauspost/cpuid/v2/index.js +28 -0
  41. package/dist/gs/github.com/klauspost/cpuid/v2/index.js.map +1 -0
  42. package/dist/gs/github.com/pkg/errors/errors.d.ts +0 -2
  43. package/dist/gs/github.com/pkg/errors/errors.js.map +1 -1
  44. package/dist/gs/github.com/pkg/errors/index.d.ts +2 -1
  45. package/dist/gs/github.com/pkg/errors/index.js +1 -1
  46. package/dist/gs/github.com/pkg/errors/index.js.map +1 -1
  47. package/dist/gs/github.com/pkg/errors/stack.d.ts +8 -19
  48. package/dist/gs/github.com/pkg/errors/stack.js +26 -61
  49. package/dist/gs/github.com/pkg/errors/stack.js.map +1 -1
  50. package/dist/gs/golang.org/x/crypto/cryptobyte/asn1/index.d.ts +19 -0
  51. package/dist/gs/golang.org/x/crypto/cryptobyte/asn1/index.js +25 -0
  52. package/dist/gs/golang.org/x/crypto/cryptobyte/asn1/index.js.map +1 -0
  53. package/dist/gs/golang.org/x/crypto/cryptobyte/index.d.ts +104 -0
  54. package/dist/gs/golang.org/x/crypto/cryptobyte/index.js +1107 -0
  55. package/dist/gs/golang.org/x/crypto/cryptobyte/index.js.map +1 -0
  56. package/dist/gs/golang.org/x/crypto/internal/alias/index.d.ts +3 -0
  57. package/dist/gs/golang.org/x/crypto/internal/alias/index.js +39 -0
  58. package/dist/gs/golang.org/x/crypto/internal/alias/index.js.map +1 -0
  59. package/dist/gs/runtime/runtime.d.ts +6 -1
  60. package/dist/gs/runtime/runtime.js +15 -8
  61. package/dist/gs/runtime/runtime.js.map +1 -1
  62. package/dist/gs/runtime/trace/index.d.ts +8 -5
  63. package/dist/gs/runtime/trace/index.js +324 -23
  64. package/dist/gs/runtime/trace/index.js.map +1 -1
  65. package/dist/gs/slices/slices.d.ts +2 -1
  66. package/dist/gs/slices/slices.js +9 -3
  67. package/dist/gs/slices/slices.js.map +1 -1
  68. package/dist/gs/sort/search.gs.d.ts +3 -1
  69. package/dist/gs/sort/search.gs.js +18 -53
  70. package/dist/gs/sort/search.gs.js.map +1 -1
  71. package/dist/gs/sync/sync.d.ts +1 -1
  72. package/dist/gs/sync/sync.js +3 -0
  73. package/dist/gs/sync/sync.js.map +1 -1
  74. package/dist/gs/time/time.d.ts +22 -29
  75. package/dist/gs/time/time.js +111 -32
  76. package/dist/gs/time/time.js.map +1 -1
  77. package/dist/gs/unsafe/unsafe.d.ts +3 -2
  78. package/dist/gs/unsafe/unsafe.js.map +1 -1
  79. package/go.mod +7 -5
  80. package/go.sum +12 -26
  81. package/gs/database/sql/driver/index.test.ts +88 -0
  82. package/gs/database/sql/driver/index.ts +675 -0
  83. package/gs/database/sql/driver/meta.json +3 -0
  84. package/gs/database/sql/driver/parity.json +144 -0
  85. package/gs/encoding/binary/index.test.ts +239 -0
  86. package/gs/encoding/binary/index.ts +999 -0
  87. package/gs/encoding/binary/meta.json +9 -0
  88. package/gs/encoding/binary/parity.json +72 -0
  89. package/gs/fmt/fmt.test.ts +28 -0
  90. package/gs/fmt/fmt.ts +198 -61
  91. package/gs/fmt/meta.json +2 -1
  92. package/gs/github.com/klauspost/cpuid/v2/index.ts +38 -0
  93. package/gs/github.com/klauspost/cpuid/v2/meta.json +3 -0
  94. package/gs/github.com/pkg/errors/errors.ts +1 -2
  95. package/gs/github.com/pkg/errors/index.ts +2 -1
  96. package/gs/github.com/pkg/errors/stack.ts +34 -62
  97. package/gs/golang.org/x/crypto/cryptobyte/asn1/index.test.ts +19 -0
  98. package/gs/golang.org/x/crypto/cryptobyte/asn1/index.ts +29 -0
  99. package/gs/golang.org/x/crypto/cryptobyte/index.test.ts +255 -0
  100. package/gs/golang.org/x/crypto/cryptobyte/index.ts +1441 -0
  101. package/gs/golang.org/x/crypto/cryptobyte/meta.json +3 -0
  102. package/gs/golang.org/x/crypto/internal/alias/index.test.ts +40 -0
  103. package/gs/golang.org/x/crypto/internal/alias/index.ts +40 -0
  104. package/gs/runtime/runtime.test.ts +16 -0
  105. package/gs/runtime/runtime.ts +17 -9
  106. package/gs/runtime/trace/index.test.ts +113 -14
  107. package/gs/runtime/trace/index.ts +384 -34
  108. package/gs/runtime/trace/meta.json +1 -0
  109. package/gs/slices/slices.test.ts +24 -1
  110. package/gs/slices/slices.ts +14 -4
  111. package/gs/sort/meta.json +1 -0
  112. package/gs/sort/search.gs.ts +20 -5
  113. package/gs/sync/sync.ts +4 -1
  114. package/gs/time/time.test.ts +79 -2
  115. package/gs/time/time.ts +133 -33
  116. package/gs/unsafe/unsafe.ts +4 -2
  117. package/package.json +2 -2
@@ -0,0 +1,999 @@
1
+ import * as $ from '@goscript/builtin/index.js'
2
+ import * as io from '@goscript/io/index.js'
3
+
4
+ export interface ByteOrder {
5
+ Uint16(b: $.Slice<number>): number
6
+ Uint32(b: $.Slice<number>): number
7
+ Uint64(b: $.Slice<number>): number
8
+ PutUint16(b: $.Slice<number>, v: number): void
9
+ PutUint32(b: $.Slice<number>, v: number): void
10
+ PutUint64(b: $.Slice<number>, v: number): void
11
+ String(): string
12
+ }
13
+
14
+ export interface AppendByteOrder {
15
+ AppendUint16(b: $.Slice<number>, v: number): $.Slice<number>
16
+ AppendUint32(b: $.Slice<number>, v: number): $.Slice<number>
17
+ AppendUint64(b: $.Slice<number>, v: number): $.Slice<number>
18
+ String(): string
19
+ }
20
+
21
+ type fixedKind =
22
+ | 'bool'
23
+ | 'int8'
24
+ | 'uint8'
25
+ | 'int16'
26
+ | 'uint16'
27
+ | 'int32'
28
+ | 'uint32'
29
+ | 'int64'
30
+ | 'uint64'
31
+ | 'float32'
32
+ | 'float64'
33
+ | '[]bool'
34
+ | '[]int8'
35
+ | '[]uint8'
36
+ | '[]int16'
37
+ | '[]uint16'
38
+ | '[]int32'
39
+ | '[]uint32'
40
+ | '[]int64'
41
+ | '[]uint64'
42
+ | '[]float32'
43
+ | '[]float64'
44
+
45
+ type boxedValue = {
46
+ __goType?: string
47
+ __goTypeInfo?: $.TypeInfo | string
48
+ __goValue?: unknown
49
+ }
50
+
51
+ type decodedTarget = {
52
+ kind: fixedKind
53
+ value: unknown
54
+ settable: ((value: unknown) => void) | null
55
+ }
56
+
57
+ type byteReader = {
58
+ ReadByte(): [number, $.GoError] | Promise<[number, $.GoError]>
59
+ }
60
+
61
+ const errBufferTooSmall = $.newError('buffer too small')
62
+ const errOverflow = $.newError('binary: varint overflows a 64-bit integer')
63
+
64
+ export const MaxVarintLen16 = 3
65
+ export const MaxVarintLen32 = 5
66
+ export const MaxVarintLen64 = 10
67
+
68
+ class littleEndian implements ByteOrder, AppendByteOrder {
69
+ public Uint(b: $.Slice<number>): number {
70
+ return this.Uint64(b)
71
+ }
72
+
73
+ public Uint16(b: $.Slice<number>): number {
74
+ requireLen(b, 2)
75
+ return byteAt(b, 0) | (byteAt(b, 1) << 8)
76
+ }
77
+
78
+ public Uint32(b: $.Slice<number>): number {
79
+ requireLen(b, 4)
80
+ return (
81
+ (byteAt(b, 0) |
82
+ (byteAt(b, 1) << 8) |
83
+ (byteAt(b, 2) << 16) |
84
+ (byteAt(b, 3) << 24)) >>>
85
+ 0
86
+ )
87
+ }
88
+
89
+ public Uint64(b: $.Slice<number>): number {
90
+ requireLen(b, 8)
91
+ let value = 0n
92
+ for (let i = 0; i < 8; i++) {
93
+ value |= BigInt(byteAt(b, i)) << BigInt(8 * i)
94
+ }
95
+ return uint64Result(value)
96
+ }
97
+
98
+ public PutUint16(b: $.Slice<number>, v: number): void {
99
+ requireLen(b, 2)
100
+ setByte(b, 0, v)
101
+ setByte(b, 1, v >> 8)
102
+ }
103
+
104
+ public PutUint32(b: $.Slice<number>, v: number): void {
105
+ requireLen(b, 4)
106
+ const value = Number($.uint(v, 32))
107
+ setByte(b, 0, value)
108
+ setByte(b, 1, value >>> 8)
109
+ setByte(b, 2, value >>> 16)
110
+ setByte(b, 3, value >>> 24)
111
+ }
112
+
113
+ public PutUint64(b: $.Slice<number>, v: number): void {
114
+ requireLen(b, 8)
115
+ const value = toUint64(v)
116
+ for (let i = 0; i < 8; i++) {
117
+ setByte(b, i, Number((value >> BigInt(8 * i)) & 0xffn))
118
+ }
119
+ }
120
+
121
+ public AppendUint16(b: $.Slice<number>, v: number): $.Slice<number> {
122
+ return $.append(b, v, v >> 8)
123
+ }
124
+
125
+ public AppendUint32(b: $.Slice<number>, v: number): $.Slice<number> {
126
+ const value = Number($.uint(v, 32))
127
+ return $.append(b, value, value >>> 8, value >>> 16, value >>> 24)
128
+ }
129
+
130
+ public AppendUint64(b: $.Slice<number>, v: number): $.Slice<number> {
131
+ let out = b
132
+ const value = toUint64(v)
133
+ for (let i = 0; i < 8; i++) {
134
+ out = $.append(out, Number((value >> BigInt(8 * i)) & 0xffn))
135
+ }
136
+ return out
137
+ }
138
+
139
+ public String(): string {
140
+ return 'LittleEndian'
141
+ }
142
+
143
+ public GoString(): string {
144
+ return 'binary.LittleEndian'
145
+ }
146
+
147
+ public clone(): littleEndian {
148
+ return $.markAsStructValue(new littleEndian())
149
+ }
150
+ }
151
+
152
+ class bigEndian implements ByteOrder, AppendByteOrder {
153
+ public Uint(b: $.Slice<number>): number {
154
+ return this.Uint64(b)
155
+ }
156
+
157
+ public Uint16(b: $.Slice<number>): number {
158
+ requireLen(b, 2)
159
+ return byteAt(b, 1) | (byteAt(b, 0) << 8)
160
+ }
161
+
162
+ public Uint32(b: $.Slice<number>): number {
163
+ requireLen(b, 4)
164
+ return (
165
+ (byteAt(b, 3) |
166
+ (byteAt(b, 2) << 8) |
167
+ (byteAt(b, 1) << 16) |
168
+ (byteAt(b, 0) << 24)) >>>
169
+ 0
170
+ )
171
+ }
172
+
173
+ public Uint64(b: $.Slice<number>): number {
174
+ requireLen(b, 8)
175
+ let value = 0n
176
+ for (let i = 0; i < 8; i++) {
177
+ value = (value << 8n) | BigInt(byteAt(b, i))
178
+ }
179
+ return uint64Result(value)
180
+ }
181
+
182
+ public PutUint16(b: $.Slice<number>, v: number): void {
183
+ requireLen(b, 2)
184
+ setByte(b, 0, v >> 8)
185
+ setByte(b, 1, v)
186
+ }
187
+
188
+ public PutUint32(b: $.Slice<number>, v: number): void {
189
+ requireLen(b, 4)
190
+ const value = Number($.uint(v, 32))
191
+ setByte(b, 0, value >>> 24)
192
+ setByte(b, 1, value >>> 16)
193
+ setByte(b, 2, value >>> 8)
194
+ setByte(b, 3, value)
195
+ }
196
+
197
+ public PutUint64(b: $.Slice<number>, v: number): void {
198
+ requireLen(b, 8)
199
+ const value = toUint64(v)
200
+ for (let i = 0; i < 8; i++) {
201
+ setByte(b, i, Number((value >> BigInt(56 - 8 * i)) & 0xffn))
202
+ }
203
+ }
204
+
205
+ public AppendUint16(b: $.Slice<number>, v: number): $.Slice<number> {
206
+ return $.append(b, v >> 8, v)
207
+ }
208
+
209
+ public AppendUint32(b: $.Slice<number>, v: number): $.Slice<number> {
210
+ const value = Number($.uint(v, 32))
211
+ return $.append(b, value >>> 24, value >>> 16, value >>> 8, value)
212
+ }
213
+
214
+ public AppendUint64(b: $.Slice<number>, v: number): $.Slice<number> {
215
+ let out = b
216
+ const value = toUint64(v)
217
+ for (let i = 0; i < 8; i++) {
218
+ out = $.append(out, Number((value >> BigInt(56 - 8 * i)) & 0xffn))
219
+ }
220
+ return out
221
+ }
222
+
223
+ public String(): string {
224
+ return 'BigEndian'
225
+ }
226
+
227
+ public GoString(): string {
228
+ return 'binary.BigEndian'
229
+ }
230
+
231
+ public clone(): bigEndian {
232
+ return $.markAsStructValue(new bigEndian())
233
+ }
234
+ }
235
+
236
+ export const LittleEndian = new littleEndian()
237
+ export const BigEndian = new bigEndian()
238
+ export const NativeEndian = LittleEndian
239
+
240
+ $.registerInterfaceType('binary.ByteOrder', null, [
241
+ {
242
+ name: 'Uint16',
243
+ args: [byteSliceArg('b')],
244
+ returns: [numberReturn()],
245
+ },
246
+ {
247
+ name: 'Uint32',
248
+ args: [byteSliceArg('b')],
249
+ returns: [numberReturn()],
250
+ },
251
+ {
252
+ name: 'Uint64',
253
+ args: [byteSliceArg('b')],
254
+ returns: [numberReturn()],
255
+ },
256
+ {
257
+ name: 'PutUint16',
258
+ args: [byteSliceArg('b'), numberArg('v')],
259
+ returns: [],
260
+ },
261
+ {
262
+ name: 'PutUint32',
263
+ args: [byteSliceArg('b'), numberArg('v')],
264
+ returns: [],
265
+ },
266
+ {
267
+ name: 'PutUint64',
268
+ args: [byteSliceArg('b'), numberArg('v')],
269
+ returns: [],
270
+ },
271
+ {
272
+ name: 'String',
273
+ args: [],
274
+ returns: [{ type: { kind: $.TypeKind.Basic, name: 'string' } }],
275
+ },
276
+ ])
277
+
278
+ $.registerInterfaceType('binary.AppendByteOrder', null, [
279
+ {
280
+ name: 'AppendUint16',
281
+ args: [byteSliceArg('b'), numberArg('v')],
282
+ returns: [{ type: byteSliceType() }],
283
+ },
284
+ {
285
+ name: 'AppendUint32',
286
+ args: [byteSliceArg('b'), numberArg('v')],
287
+ returns: [{ type: byteSliceType() }],
288
+ },
289
+ {
290
+ name: 'AppendUint64',
291
+ args: [byteSliceArg('b'), numberArg('v')],
292
+ returns: [{ type: byteSliceType() }],
293
+ },
294
+ {
295
+ name: 'String',
296
+ args: [],
297
+ returns: [{ type: { kind: $.TypeKind.Basic, name: 'string' } }],
298
+ },
299
+ ])
300
+
301
+ export function AppendUvarint(
302
+ buf: $.Slice<number>,
303
+ x: number,
304
+ ): $.Slice<number> {
305
+ let out = buf
306
+ let value = toUint64(x)
307
+ while (value >= 0x80n) {
308
+ out = $.append(out, Number(value & 0x7fn) | 0x80)
309
+ value >>= 7n
310
+ }
311
+ return $.append(out, Number(value))
312
+ }
313
+
314
+ export function PutUvarint(buf: $.Slice<number>, x: number): number {
315
+ let value = toUint64(x)
316
+ let i = 0
317
+ while (value >= 0x80n) {
318
+ setByte(buf, i, Number(value & 0x7fn) | 0x80)
319
+ value >>= 7n
320
+ i++
321
+ }
322
+ setByte(buf, i, Number(value))
323
+ return i + 1
324
+ }
325
+
326
+ export function Uvarint(buf: $.Slice<number>): [number, number] {
327
+ let x = 0n
328
+ let s = 0n
329
+ for (let i = 0; i < $.len(buf); i++) {
330
+ const b = byteAt(buf, i)
331
+ if (i === MaxVarintLen64) {
332
+ return [0, -(i + 1)]
333
+ }
334
+ if (b < 0x80) {
335
+ if (i === MaxVarintLen64 - 1 && b > 1) {
336
+ return [0, -(i + 1)]
337
+ }
338
+ return [uint64Result(x | (BigInt(b) << s)), i + 1]
339
+ }
340
+ x |= BigInt(b & 0x7f) << s
341
+ s += 7n
342
+ }
343
+ return [0, 0]
344
+ }
345
+
346
+ export function AppendVarint(buf: $.Slice<number>, x: number): $.Slice<number> {
347
+ return AppendUvarint(buf, encodeSignedVarint(x))
348
+ }
349
+
350
+ export function PutVarint(buf: $.Slice<number>, x: number): number {
351
+ return PutUvarint(buf, encodeSignedVarint(x))
352
+ }
353
+
354
+ export function Varint(buf: $.Slice<number>): [number, number] {
355
+ const [ux, n] = Uvarint(buf)
356
+ return [decodeSignedVarint(ux), n]
357
+ }
358
+
359
+ export async function ReadUvarint(r: byteReader): Promise<[number, $.GoError]> {
360
+ let x = 0n
361
+ let s = 0n
362
+ for (let i = 0; i < MaxVarintLen64; i++) {
363
+ const [b, err] = await r.ReadByte()
364
+ if (err !== null) {
365
+ return [uint64Result(x), i > 0 && isEOF(err) ? io.ErrUnexpectedEOF : err]
366
+ }
367
+ if (b < 0x80) {
368
+ if (i === MaxVarintLen64 - 1 && b > 1) {
369
+ return [uint64Result(x), errOverflow]
370
+ }
371
+ return [uint64Result(x | (BigInt(b) << s)), null]
372
+ }
373
+ x |= BigInt(b & 0x7f) << s
374
+ s += 7n
375
+ }
376
+ return [uint64Result(x), errOverflow]
377
+ }
378
+
379
+ export async function ReadVarint(r: byteReader): Promise<[number, $.GoError]> {
380
+ const [ux, err] = await ReadUvarint(r)
381
+ return [decodeSignedVarint(ux), err]
382
+ }
383
+
384
+ export async function Read(
385
+ r: io.Reader,
386
+ order: ByteOrder | null,
387
+ data: unknown,
388
+ ): Promise<$.GoError> {
389
+ const byteOrder = requireByteOrder(order)
390
+ const target = decodeTarget(data)
391
+ if (target === null) {
392
+ return unsupportedError('Read', data)
393
+ }
394
+ const size = fixedSize(target.kind, target.value)
395
+ if (size < 0) {
396
+ return unsupportedError('Read', data)
397
+ }
398
+ const buf = $.makeSlice<number>(size, undefined, 'byte')
399
+ const [, err] = await readFull(r, buf)
400
+ if (err !== null) {
401
+ return err
402
+ }
403
+ decodeFixed(buf, byteOrder, target)
404
+ return null
405
+ }
406
+
407
+ export function Decode(
408
+ buf: $.Slice<number>,
409
+ order: ByteOrder | null,
410
+ data: unknown,
411
+ ): [number, $.GoError] {
412
+ const byteOrder = requireByteOrder(order)
413
+ const target = decodeTarget(data)
414
+ if (target === null) {
415
+ return [0, unsupportedError('Decode', data)]
416
+ }
417
+ const size = fixedSize(target.kind, target.value)
418
+ if (size < 0) {
419
+ return [0, unsupportedError('Decode', data)]
420
+ }
421
+ if ($.len(buf) < size) {
422
+ return [0, errBufferTooSmall]
423
+ }
424
+ decodeFixed($.goSlice(buf, 0, size), byteOrder, target)
425
+ return [size, null]
426
+ }
427
+
428
+ export async function Write(
429
+ w: io.Writer,
430
+ order: ByteOrder | null,
431
+ data: unknown,
432
+ ): Promise<$.GoError> {
433
+ const encoded = encodeData(requireByteOrder(order), data)
434
+ if (encoded === null) {
435
+ return unsupportedError('Write', data)
436
+ }
437
+ const [, err] = await w.Write(encoded)
438
+ return err
439
+ }
440
+
441
+ export function Encode(
442
+ buf: $.Slice<number>,
443
+ order: ByteOrder | null,
444
+ data: unknown,
445
+ ): [number, $.GoError] {
446
+ const encoded = encodeData(requireByteOrder(order), data)
447
+ if (encoded === null) {
448
+ return [0, unsupportedError('Encode', data)]
449
+ }
450
+ if ($.len(buf) < $.len(encoded)) {
451
+ return [0, errBufferTooSmall]
452
+ }
453
+ $.copy(buf, encoded)
454
+ return [$.len(encoded), null]
455
+ }
456
+
457
+ export function Append(
458
+ buf: $.Slice<number>,
459
+ order: ByteOrder | null,
460
+ data: unknown,
461
+ ): [$.Slice<number>, $.GoError] {
462
+ const encoded = encodeData(requireByteOrder(order), data)
463
+ if (encoded === null) {
464
+ return [null, unsupportedError('Append', data)]
465
+ }
466
+ return [$.appendSlice(buf, encoded), null]
467
+ }
468
+
469
+ export function Size(v: unknown): number {
470
+ const target = decodeTarget(v)
471
+ if (target === null) {
472
+ return -1
473
+ }
474
+ return fixedSize(target.kind, target.value)
475
+ }
476
+
477
+ function requireByteOrder(order: ByteOrder | null): ByteOrder {
478
+ if (order === null) {
479
+ throw new Error(
480
+ 'runtime error: invalid memory address or nil pointer dereference',
481
+ )
482
+ }
483
+ return order
484
+ }
485
+
486
+ function decodeFixed(
487
+ buf: $.Slice<number>,
488
+ order: ByteOrder,
489
+ target: decodedTarget,
490
+ ): void {
491
+ if (target.kind.startsWith('[]')) {
492
+ decodeFixedSlice(buf, order, target.kind, target.value)
493
+ return
494
+ }
495
+ if (target.settable === null) {
496
+ return
497
+ }
498
+ target.settable(decodeScalar(buf, order, target.kind))
499
+ }
500
+
501
+ function decodeFixedSlice(
502
+ buf: $.Slice<number>,
503
+ order: ByteOrder,
504
+ kind: fixedKind,
505
+ target: unknown,
506
+ ): void {
507
+ const elemKind = kind.slice(2) as fixedKind
508
+ const width = fixedSize(elemKind, 0)
509
+ const count = $.len(target as $.Slice<unknown>)
510
+ for (let i = 0; i < count; i++) {
511
+ ;(target as any)[i] = decodeScalar(
512
+ $.goSlice(buf, i * width, i * width + width),
513
+ order,
514
+ elemKind,
515
+ )
516
+ }
517
+ }
518
+
519
+ function encodeData(order: ByteOrder, data: unknown): $.Slice<number> | null {
520
+ const target = decodeTarget(data)
521
+ if (target === null) {
522
+ return null
523
+ }
524
+ const size = fixedSize(target.kind, target.value)
525
+ if (size < 0) {
526
+ return null
527
+ }
528
+ const out = $.makeSlice<number>(size, undefined, 'byte')
529
+ encodeFixed(out, order, target.kind, target.value)
530
+ return out
531
+ }
532
+
533
+ function encodeFixed(
534
+ buf: $.Slice<number>,
535
+ order: ByteOrder,
536
+ kind: fixedKind,
537
+ value: unknown,
538
+ ): void {
539
+ if (kind.startsWith('[]')) {
540
+ const elemKind = kind.slice(2) as fixedKind
541
+ const width = fixedSize(elemKind, 0)
542
+ const count = $.len(value as $.Slice<unknown>)
543
+ for (let i = 0; i < count; i++) {
544
+ encodeScalar(
545
+ $.goSlice(buf, i * width, i * width + width),
546
+ order,
547
+ elemKind,
548
+ (value as any)[i],
549
+ )
550
+ }
551
+ return
552
+ }
553
+ encodeScalar(buf, order, kind, value)
554
+ }
555
+
556
+ function decodeScalar(
557
+ buf: $.Slice<number>,
558
+ order: ByteOrder,
559
+ kind: fixedKind,
560
+ ): unknown {
561
+ switch (kind) {
562
+ case 'bool':
563
+ return byteAt(buf, 0) !== 0
564
+ case 'int8':
565
+ return intN(byteAt(buf, 0), 8)
566
+ case 'uint8':
567
+ return byteAt(buf, 0)
568
+ case 'int16':
569
+ return intN(order.Uint16(buf), 16)
570
+ case 'uint16':
571
+ return order.Uint16(buf)
572
+ case 'int32':
573
+ return intN(order.Uint32(buf), 32)
574
+ case 'uint32':
575
+ return order.Uint32(buf)
576
+ case 'int64':
577
+ return int64Result(toUint64(order.Uint64(buf)))
578
+ case 'uint64':
579
+ return order.Uint64(buf)
580
+ case 'float32':
581
+ return float32FromBits(order.Uint32(buf))
582
+ case 'float64':
583
+ return float64FromBits(order.Uint64(buf))
584
+ default:
585
+ return 0
586
+ }
587
+ }
588
+
589
+ function encodeScalar(
590
+ buf: $.Slice<number>,
591
+ order: ByteOrder,
592
+ kind: fixedKind,
593
+ value: unknown,
594
+ ): void {
595
+ switch (kind) {
596
+ case 'bool':
597
+ setByte(buf, 0, value ? 1 : 0)
598
+ return
599
+ case 'int8':
600
+ case 'uint8':
601
+ setByte(buf, 0, Number(value))
602
+ return
603
+ case 'int16':
604
+ case 'uint16':
605
+ order.PutUint16(buf, Number(value))
606
+ return
607
+ case 'int32':
608
+ case 'uint32':
609
+ order.PutUint32(buf, Number(value))
610
+ return
611
+ case 'int64':
612
+ case 'uint64':
613
+ order.PutUint64(buf, value as number)
614
+ return
615
+ case 'float32':
616
+ order.PutUint32(buf, float32Bits(Number(value)))
617
+ return
618
+ case 'float64':
619
+ order.PutUint64(buf, float64Bits(Number(value)) as unknown as number)
620
+ return
621
+ }
622
+ }
623
+
624
+ function decodeTarget(data: unknown): decodedTarget | null {
625
+ const typeName = goTypeName(data)
626
+ const value = goValue(data)
627
+ if (typeName !== '') {
628
+ const kind =
629
+ fixedKindFromType(typeName) ?? fixedKindFromTypeInfo(goTypeInfo(data))
630
+ if (kind !== null) {
631
+ return {
632
+ kind,
633
+ value: pointerValueForKind(typeName, value),
634
+ settable: setterFor(typeName, value),
635
+ }
636
+ }
637
+ return null
638
+ }
639
+ if (value instanceof Uint8Array) {
640
+ return { kind: '[]uint8', value, settable: null }
641
+ }
642
+ if (Array.isArray(value)) {
643
+ if (value.every((item) => typeof item === 'boolean')) {
644
+ return { kind: '[]bool', value, settable: null }
645
+ }
646
+ if (value.every((item) => typeof item === 'number')) {
647
+ return { kind: '[]uint8', value, settable: null }
648
+ }
649
+ }
650
+ return null
651
+ }
652
+
653
+ function pointerValueForKind(typeName: string, value: unknown): unknown {
654
+ if (typeName.startsWith('*')) {
655
+ return $.pointerValue(value as any)
656
+ }
657
+ return value
658
+ }
659
+
660
+ function setterFor(
661
+ typeName: string,
662
+ value: unknown,
663
+ ): ((value: unknown) => void) | null {
664
+ if (!typeName.startsWith('*')) {
665
+ return null
666
+ }
667
+ if ($.isVarRef(value)) {
668
+ return (next: unknown) => {
669
+ value.value = next
670
+ }
671
+ }
672
+ if (isBoxedValue(value) && $.isVarRef(value.__goValue)) {
673
+ const ref = value.__goValue
674
+ return (next: unknown) => {
675
+ ref.value = next
676
+ }
677
+ }
678
+ return null
679
+ }
680
+
681
+ function goTypeName(value: unknown): string {
682
+ if (isBoxedValue(value) && typeof value.__goType === 'string') {
683
+ return value.__goType
684
+ }
685
+ if (
686
+ value !== null &&
687
+ typeof value === 'object' &&
688
+ typeof (value as { __goType?: unknown }).__goType === 'string'
689
+ ) {
690
+ return (value as { __goType: string }).__goType
691
+ }
692
+ return ''
693
+ }
694
+
695
+ function goTypeInfo(value: unknown): $.TypeInfo | string | undefined {
696
+ if (isBoxedValue(value)) {
697
+ return value.__goTypeInfo
698
+ }
699
+ if (value !== null && typeof value === 'object') {
700
+ return (value as { __goTypeInfo?: $.TypeInfo | string }).__goTypeInfo
701
+ }
702
+ return undefined
703
+ }
704
+
705
+ function goValue(value: unknown): unknown {
706
+ if (isBoxedValue(value) && '__goValue' in value) {
707
+ return value.__goValue
708
+ }
709
+ return value
710
+ }
711
+
712
+ function isBoxedValue(value: unknown): value is boxedValue {
713
+ return value !== null && typeof value === 'object' && '__goValue' in value
714
+ }
715
+
716
+ function fixedKindFromType(typeName: string): fixedKind | null {
717
+ let name = typeName
718
+ while (name.startsWith('*')) {
719
+ name = name.slice(1)
720
+ }
721
+ if (name === 'byte') {
722
+ return 'uint8'
723
+ }
724
+ if (name === '[]byte') {
725
+ return '[]uint8'
726
+ }
727
+ if (fixedKinds.has(name)) {
728
+ return name as fixedKind
729
+ }
730
+ return null
731
+ }
732
+
733
+ function fixedKindFromTypeInfo(
734
+ info: $.TypeInfo | string | undefined,
735
+ ): fixedKind | null {
736
+ if (info === undefined) {
737
+ return null
738
+ }
739
+ if (typeof info === 'string') {
740
+ return fixedKindFromType(info)
741
+ }
742
+ switch (info.kind) {
743
+ case $.TypeKind.Pointer:
744
+ return fixedKindFromTypeInfo(info.elemType)
745
+ case $.TypeKind.Basic:
746
+ return fixedKindFromBasicName(info.name)
747
+ case $.TypeKind.Slice: {
748
+ const elemKind = fixedKindFromTypeInfo(info.elemType)
749
+ return elemKind === null ? null : fixedSliceKind(elemKind)
750
+ }
751
+ case $.TypeKind.Array: {
752
+ const elemKind = fixedKindFromTypeInfo(info.elemType)
753
+ return elemKind === null ? null : fixedSliceKind(elemKind)
754
+ }
755
+ default:
756
+ return null
757
+ }
758
+ }
759
+
760
+ function fixedKindFromBasicName(name: string | undefined): fixedKind | null {
761
+ if (name === undefined) {
762
+ return null
763
+ }
764
+ if (name === 'byte') {
765
+ return 'uint8'
766
+ }
767
+ if (name === 'rune') {
768
+ return 'int32'
769
+ }
770
+ return fixedKinds.has(name) && !name.startsWith('[]') ?
771
+ (name as fixedKind)
772
+ : null
773
+ }
774
+
775
+ function fixedSliceKind(elemKind: fixedKind): fixedKind | null {
776
+ return elemKind.startsWith('[]') ? null : (`[]${elemKind}` as fixedKind)
777
+ }
778
+
779
+ function fixedSize(kind: fixedKind, value: unknown): number {
780
+ if (kind.startsWith('[]')) {
781
+ const elemKind = kind.slice(2) as fixedKind
782
+ const elemSize = fixedSize(elemKind, 0)
783
+ return elemSize < 0 ? -1 : elemSize * $.len(value as $.Slice<unknown>)
784
+ }
785
+ switch (kind) {
786
+ case 'bool':
787
+ case 'int8':
788
+ case 'uint8':
789
+ return 1
790
+ case 'int16':
791
+ case 'uint16':
792
+ return 2
793
+ case 'int32':
794
+ case 'uint32':
795
+ case 'float32':
796
+ return 4
797
+ case 'int64':
798
+ case 'uint64':
799
+ case 'float64':
800
+ return 8
801
+ }
802
+ return -1
803
+ }
804
+
805
+ function unsupportedError(fn: string, data: unknown): $.GoError {
806
+ return $.newError(
807
+ `encoding/binary: ${fn} of ${unsupportedKind(data)} is not supported in the GoScript browser build`,
808
+ )
809
+ }
810
+
811
+ function unsupportedKind(data: unknown): string {
812
+ const typeName = goTypeName(data)
813
+ if (typeName !== '') {
814
+ return typeName
815
+ }
816
+ if ($.isVarRef(data)) {
817
+ return 'untyped pointer'
818
+ }
819
+ if (Array.isArray(data)) {
820
+ return 'array'
821
+ }
822
+ if (data === null || data === undefined) {
823
+ return '<nil>'
824
+ }
825
+ return typeof data
826
+ }
827
+
828
+ async function readFull(
829
+ r: io.Reader,
830
+ buf: $.Slice<number>,
831
+ ): Promise<[number, $.GoError]> {
832
+ let offset = 0
833
+ while (offset < $.len(buf)) {
834
+ const [n, err] = await r.Read($.goSlice(buf, offset))
835
+ offset += n
836
+ if (err !== null) {
837
+ return [offset, offset > 0 && isEOF(err) ? io.ErrUnexpectedEOF : err]
838
+ }
839
+ if (n === 0) {
840
+ return [offset, io.ErrUnexpectedEOF]
841
+ }
842
+ }
843
+ return [offset, null]
844
+ }
845
+
846
+ function requireLen(b: $.Slice<number>, n: number): void {
847
+ const length = $.len(b)
848
+ if (length < n) {
849
+ $.panic(
850
+ `runtime error: index out of range [${n - 1}] with length ${length}`,
851
+ )
852
+ }
853
+ }
854
+
855
+ function byteAt(b: $.Slice<number>, i: number): number {
856
+ return Number((b as any)[i]) & 0xff
857
+ }
858
+
859
+ function setByte(b: $.Slice<number>, i: number, v: number): void {
860
+ requireLen(b, i + 1)
861
+ ;(b as any)[i] = Number(v) & 0xff
862
+ }
863
+
864
+ function encodeSignedVarint(x: number): number {
865
+ let ux = BigInt.asUintN(64, BigInt.asIntN(64, toBigInt(x)) << 1n)
866
+ if (isNegativeInt64(x)) {
867
+ ux = BigInt.asUintN(64, ~ux)
868
+ }
869
+ return uint64Result(ux)
870
+ }
871
+
872
+ function decodeSignedVarint(uxValue: number): number {
873
+ const ux = toUint64(uxValue)
874
+ let x = ux >> 1n
875
+ if ((ux & 1n) !== 0n) {
876
+ x = BigInt.asIntN(64, ~x)
877
+ }
878
+ return int64Result(x)
879
+ }
880
+
881
+ function toUint64(value: number | bigint): bigint {
882
+ if (typeof value === 'bigint') {
883
+ return BigInt.asUintN(64, value)
884
+ }
885
+ return BigInt.asUintN(64, BigInt(Math.trunc(value)))
886
+ }
887
+
888
+ function toBigInt(value: number | bigint): bigint {
889
+ if (typeof value === 'bigint') {
890
+ return value
891
+ }
892
+ return BigInt(Math.trunc(value))
893
+ }
894
+
895
+ function isNegativeInt64(value: number | bigint): boolean {
896
+ return typeof value === 'bigint' ? value < 0n : value < 0
897
+ }
898
+
899
+ function uint64Result(value: bigint): number {
900
+ const normalized = BigInt.asUintN(64, value)
901
+ if (normalized <= BigInt(Number.MAX_SAFE_INTEGER)) {
902
+ return Number(normalized)
903
+ }
904
+ return normalized as unknown as number
905
+ }
906
+
907
+ function int64Result(value: bigint): number {
908
+ const normalized = BigInt.asIntN(64, value)
909
+ if (
910
+ normalized >= BigInt(Number.MIN_SAFE_INTEGER) &&
911
+ normalized <= BigInt(Number.MAX_SAFE_INTEGER)
912
+ ) {
913
+ return Number(normalized)
914
+ }
915
+ return normalized as unknown as number
916
+ }
917
+
918
+ function intN(value: number, bits: number): number {
919
+ const sign = 1 << (bits - 1)
920
+ const mask = bits === 32 ? 0xffffffff : (1 << bits) - 1
921
+ const normalized = value & mask
922
+ return (normalized & sign) !== 0 ? normalized - (1 << bits) : normalized
923
+ }
924
+
925
+ function float32Bits(value: number): number {
926
+ const bytes = new ArrayBuffer(4)
927
+ const view = new DataView(bytes)
928
+ view.setFloat32(0, value, true)
929
+ return view.getUint32(0, true)
930
+ }
931
+
932
+ function float32FromBits(value: number): number {
933
+ const bytes = new ArrayBuffer(4)
934
+ const view = new DataView(bytes)
935
+ view.setUint32(0, Number($.uint(value, 32)), true)
936
+ return view.getFloat32(0, true)
937
+ }
938
+
939
+ function float64Bits(value: number): number | bigint {
940
+ const bytes = new ArrayBuffer(8)
941
+ const view = new DataView(bytes)
942
+ view.setFloat64(0, value, true)
943
+ return view.getBigUint64(0, true)
944
+ }
945
+
946
+ function float64FromBits(value: number): number {
947
+ const bytes = new ArrayBuffer(8)
948
+ const view = new DataView(bytes)
949
+ view.setBigUint64(0, toUint64(value), true)
950
+ return view.getFloat64(0, true)
951
+ }
952
+
953
+ function isEOF(err: $.GoError): boolean {
954
+ return err === io.EOF || err?.Error?.() === 'EOF'
955
+ }
956
+
957
+ function byteSliceArg(name: string): $.MethodArg {
958
+ return { name, type: byteSliceType() }
959
+ }
960
+
961
+ function numberArg(name: string): $.MethodArg {
962
+ return { name, type: { kind: $.TypeKind.Basic, name: 'number' } }
963
+ }
964
+
965
+ function numberReturn(): $.MethodArg {
966
+ return { type: { kind: $.TypeKind.Basic, name: 'number' } }
967
+ }
968
+
969
+ function byteSliceType(): $.TypeInfo {
970
+ return {
971
+ kind: $.TypeKind.Slice,
972
+ elemType: { kind: $.TypeKind.Basic, name: 'uint8' },
973
+ }
974
+ }
975
+
976
+ const fixedKinds = new Set<string>([
977
+ 'bool',
978
+ 'int8',
979
+ 'uint8',
980
+ 'int16',
981
+ 'uint16',
982
+ 'int32',
983
+ 'uint32',
984
+ 'int64',
985
+ 'uint64',
986
+ 'float32',
987
+ 'float64',
988
+ '[]bool',
989
+ '[]int8',
990
+ '[]uint8',
991
+ '[]int16',
992
+ '[]uint16',
993
+ '[]int32',
994
+ '[]uint32',
995
+ '[]int64',
996
+ '[]uint64',
997
+ '[]float32',
998
+ '[]float64',
999
+ ])