goscript 0.1.2 → 0.1.4
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.
- package/cmd/goscript/cmd_compile.go +28 -8
- package/cmd/goscript/cmd_compile_test.go +105 -6
- package/compiler/build-flags.go +9 -10
- package/compiler/gotest/runner_test.go +127 -0
- package/compiler/lowered-program.go +1 -0
- package/compiler/lowering.go +1325 -194
- package/compiler/lowering_bench_test.go +350 -0
- package/compiler/override-registry_test.go +43 -0
- package/compiler/package-graph.go +61 -4
- package/compiler/package-graph_test.go +30 -0
- package/compiler/semantic-model-types.go +8 -0
- package/compiler/semantic-model.go +447 -22
- package/compiler/semantic-model_test.go +138 -0
- package/compiler/skeleton_test.go +1436 -50
- package/compiler/typescript-emitter.go +47 -4
- package/dist/gs/builtin/builtin.d.ts +2 -2
- package/dist/gs/builtin/builtin.js +20 -0
- package/dist/gs/builtin/builtin.js.map +1 -1
- package/dist/gs/builtin/channel.js +36 -9
- package/dist/gs/builtin/channel.js.map +1 -1
- package/dist/gs/builtin/slice.js +5 -0
- package/dist/gs/builtin/slice.js.map +1 -1
- package/dist/gs/builtin/type.d.ts +1 -1
- package/dist/gs/builtin/type.js +80 -8
- package/dist/gs/builtin/type.js.map +1 -1
- package/dist/gs/bytes/bytes.gs.d.ts +7 -5
- package/dist/gs/bytes/bytes.gs.js +10 -4
- package/dist/gs/bytes/bytes.gs.js.map +1 -1
- package/dist/gs/compress/zlib/index.d.ts +3 -3
- package/dist/gs/compress/zlib/index.js +88 -26
- package/dist/gs/compress/zlib/index.js.map +1 -1
- package/dist/gs/crypto/sha1/index.d.ts +5 -0
- package/dist/gs/crypto/sha1/index.js +103 -0
- package/dist/gs/crypto/sha1/index.js.map +1 -0
- package/dist/gs/crypto/sha256/index.js +2 -5
- package/dist/gs/crypto/sha256/index.js.map +1 -1
- package/dist/gs/crypto/sha512/index.js +2 -5
- package/dist/gs/crypto/sha512/index.js.map +1 -1
- package/dist/gs/embed/index.d.ts +6 -0
- package/dist/gs/embed/index.js +210 -5
- package/dist/gs/embed/index.js.map +1 -1
- package/dist/gs/fmt/fmt.d.ts +4 -4
- package/dist/gs/fmt/fmt.js +93 -19
- package/dist/gs/fmt/fmt.js.map +1 -1
- package/dist/gs/github.com/aperturerobotics/starpc/srpc/index.js +118 -6
- package/dist/gs/github.com/aperturerobotics/starpc/srpc/index.js.map +1 -1
- package/dist/gs/github.com/go-git/go-billy/v6/osfs/index.d.ts +45 -0
- package/dist/gs/github.com/go-git/go-billy/v6/osfs/index.js +229 -0
- package/dist/gs/github.com/go-git/go-billy/v6/osfs/index.js.map +1 -0
- package/dist/gs/io/fs/readdir.js +5 -3
- package/dist/gs/io/fs/readdir.js.map +1 -1
- package/dist/gs/io/io.d.ts +18 -11
- package/dist/gs/io/io.js +107 -44
- package/dist/gs/io/io.js.map +1 -1
- package/dist/gs/math/bits/index.d.ts +26 -5
- package/dist/gs/math/bits/index.js +13 -24
- package/dist/gs/math/bits/index.js.map +1 -1
- package/dist/gs/net/http/httptest/index.js +7 -5
- package/dist/gs/net/http/httptest/index.js.map +1 -1
- package/dist/gs/net/http/index.d.ts +11 -1
- package/dist/gs/net/http/index.js +157 -11
- package/dist/gs/net/http/index.js.map +1 -1
- package/dist/gs/os/types_js.gs.d.ts +6 -2
- package/dist/gs/os/types_js.gs.js +169 -8
- package/dist/gs/os/types_js.gs.js.map +1 -1
- package/dist/gs/os/zero_copy_posix.gs.js +1 -1
- package/dist/gs/os/zero_copy_posix.gs.js.map +1 -1
- package/dist/gs/reflect/type.d.ts +1 -0
- package/dist/gs/reflect/type.js +80 -51
- package/dist/gs/reflect/type.js.map +1 -1
- package/dist/gs/strings/reader.d.ts +1 -1
- package/dist/gs/strings/reader.js +2 -2
- package/dist/gs/strings/reader.js.map +1 -1
- package/dist/gs/sync/sync.d.ts +2 -1
- package/dist/gs/sync/sync.js +37 -16
- package/dist/gs/sync/sync.js.map +1 -1
- package/dist/gs/syscall/js/index.js +9 -0
- package/dist/gs/syscall/js/index.js.map +1 -1
- package/dist/gs/testing/testing.js +8 -6
- package/dist/gs/testing/testing.js.map +1 -1
- package/gs/builtin/builtin.ts +25 -2
- package/gs/builtin/channel.ts +47 -9
- package/gs/builtin/runtime-contract.test.ts +78 -0
- package/gs/builtin/slice.ts +7 -0
- package/gs/builtin/type.ts +97 -8
- package/gs/bytes/bytes.gs.ts +19 -10
- package/gs/bytes/bytes.test.ts +17 -0
- package/gs/compress/zlib/index.test.ts +97 -0
- package/gs/compress/zlib/index.ts +117 -27
- package/gs/compress/zlib/meta.json +4 -1
- package/gs/context/context.test.ts +5 -1
- package/gs/crypto/sha1/index.test.ts +45 -0
- package/gs/crypto/sha1/index.ts +127 -0
- package/gs/crypto/sha1/meta.json +8 -0
- package/gs/crypto/sha256/index.test.ts +14 -2
- package/gs/crypto/sha256/index.ts +3 -6
- package/gs/crypto/sha512/index.test.ts +17 -2
- package/gs/crypto/sha512/index.ts +3 -6
- package/gs/embed/index.test.ts +87 -0
- package/gs/embed/index.ts +229 -5
- package/gs/fmt/fmt.test.ts +61 -3
- package/gs/fmt/fmt.ts +115 -22
- package/gs/fmt/meta.json +6 -1
- package/gs/github.com/aperturerobotics/starpc/srpc/index.test.ts +8 -1
- package/gs/github.com/aperturerobotics/starpc/srpc/index.ts +139 -11
- package/gs/github.com/aperturerobotics/util/conc/index.test.ts +1 -1
- package/gs/github.com/go-git/go-billy/v6/osfs/index.test.ts +110 -0
- package/gs/github.com/go-git/go-billy/v6/osfs/index.ts +280 -0
- package/gs/github.com/go-git/go-billy/v6/osfs/meta.json +8 -0
- package/gs/io/fs/readdir.test.ts +38 -0
- package/gs/io/fs/readdir.ts +7 -3
- package/gs/io/io.test.ts +135 -0
- package/gs/io/io.ts +143 -63
- package/gs/io/meta.json +7 -1
- package/gs/math/bits/index.ts +52 -28
- package/gs/net/http/httptest/index.test.ts +34 -2
- package/gs/net/http/httptest/index.ts +23 -8
- package/gs/net/http/index.test.ts +46 -0
- package/gs/net/http/index.ts +178 -12
- package/gs/os/file_unix_js.test.ts +52 -0
- package/gs/os/meta.json +4 -0
- package/gs/os/readdir.test.ts +56 -0
- package/gs/os/types_js.gs.ts +169 -8
- package/gs/os/zero_copy_posix.gs.ts +1 -2
- package/gs/reflect/deepequal.test.ts +10 -1
- package/gs/reflect/type.ts +91 -56
- package/gs/reflect/typefor.test.ts +31 -1
- package/gs/strings/meta.json +5 -2
- package/gs/strings/reader.test.ts +2 -2
- package/gs/strings/reader.ts +2 -2
- package/gs/sync/meta.json +2 -0
- package/gs/sync/sync.test.ts +41 -1
- package/gs/sync/sync.ts +41 -16
- package/gs/syscall/js/index.test.ts +18 -0
- package/gs/syscall/js/index.ts +12 -0
- package/gs/testing/testing.test.ts +32 -3
- package/gs/testing/testing.ts +13 -10
- package/package.json +1 -1
package/gs/io/io.test.ts
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import * as $ from '@goscript/builtin/index.js'
|
|
2
|
+
import { LimitedReader, MultiWriter, NopCloser, Pipe, TeeReader } from './index.js'
|
|
3
|
+
import { describe, expect, test } from 'vitest'
|
|
4
|
+
|
|
5
|
+
class sliceReader {
|
|
6
|
+
constructor(private data: Uint8Array) {}
|
|
7
|
+
|
|
8
|
+
Read(p: $.Bytes): [number, $.GoError] {
|
|
9
|
+
const n = Math.min($.len(p), this.data.length)
|
|
10
|
+
p!.set(this.data.subarray(0, n), 0)
|
|
11
|
+
this.data = this.data.subarray(n)
|
|
12
|
+
return [n, n === 0 ? (new Error('EOF') as $.GoError) : null]
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
class captureWriter {
|
|
17
|
+
public chunks: number[] = []
|
|
18
|
+
|
|
19
|
+
Write(p: $.Bytes): [number, $.GoError] {
|
|
20
|
+
this.chunks.push(...Array.from(p ?? []))
|
|
21
|
+
return [$.len(p), null]
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
describe('io override', () => {
|
|
26
|
+
test('LimitedReader accepts generated struct-literal construction', async () => {
|
|
27
|
+
const reader = new LimitedReader({
|
|
28
|
+
R: new sliceReader($.stringToBytes('abcdef')),
|
|
29
|
+
N: 3,
|
|
30
|
+
})
|
|
31
|
+
const buf = new Uint8Array(8)
|
|
32
|
+
|
|
33
|
+
const [n, err] = await reader.Read(buf)
|
|
34
|
+
|
|
35
|
+
expect(err).toBeNull()
|
|
36
|
+
expect(n).toBe(3)
|
|
37
|
+
expect(Buffer.from(buf.subarray(0, n)).toString('utf8')).toBe('abc')
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
test('TeeReader accepts nullable generated interface values', async () => {
|
|
41
|
+
const writer = new captureWriter()
|
|
42
|
+
const reader = TeeReader(new sliceReader($.stringToBytes('abc')), writer)
|
|
43
|
+
const buf = new Uint8Array(4)
|
|
44
|
+
|
|
45
|
+
const [n, err] = await reader.Read(buf)
|
|
46
|
+
|
|
47
|
+
expect(err).toBeNull()
|
|
48
|
+
expect(n).toBe(3)
|
|
49
|
+
expect(Buffer.from(writer.chunks).toString('utf8')).toBe('abc')
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
test('NopCloser accepts nullable generated interface values', () => {
|
|
53
|
+
const reader: sliceReader | null = new sliceReader($.stringToBytes('abc'))
|
|
54
|
+
const body = NopCloser(reader)
|
|
55
|
+
const buf = new Uint8Array(4)
|
|
56
|
+
|
|
57
|
+
const [n, err] = body.Read(buf)
|
|
58
|
+
|
|
59
|
+
expect(err).toBeNull()
|
|
60
|
+
expect(n).toBe(3)
|
|
61
|
+
expect(body.Close()).toBeNull()
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
test('TeeReader awaits async readers and writers', async () => {
|
|
65
|
+
const chunks: number[] = []
|
|
66
|
+
const reader = TeeReader(
|
|
67
|
+
{
|
|
68
|
+
async Read(p: $.Bytes): Promise<[number, $.GoError]> {
|
|
69
|
+
await Promise.resolve()
|
|
70
|
+
p!.set($.stringToBytes('abc'), 0)
|
|
71
|
+
return [3, null]
|
|
72
|
+
},
|
|
73
|
+
} as any,
|
|
74
|
+
{
|
|
75
|
+
async Write(p: $.Bytes): Promise<[number, $.GoError]> {
|
|
76
|
+
await Promise.resolve()
|
|
77
|
+
chunks.push(...Array.from(p ?? []))
|
|
78
|
+
return [$.len(p), null]
|
|
79
|
+
},
|
|
80
|
+
} as any,
|
|
81
|
+
)
|
|
82
|
+
const buf = new Uint8Array(4)
|
|
83
|
+
|
|
84
|
+
const [n, err] = await reader.Read(buf)
|
|
85
|
+
|
|
86
|
+
expect(err).toBeNull()
|
|
87
|
+
expect(n).toBe(3)
|
|
88
|
+
expect(Buffer.from(chunks).toString('utf8')).toBe('abc')
|
|
89
|
+
})
|
|
90
|
+
|
|
91
|
+
test('MultiWriter accepts nullable generated interface values', async () => {
|
|
92
|
+
const first = new captureWriter()
|
|
93
|
+
const second = new captureWriter()
|
|
94
|
+
const writer = MultiWriter(first, second)
|
|
95
|
+
|
|
96
|
+
const [n, err] = await writer.Write($.stringToBytes('abc'))
|
|
97
|
+
|
|
98
|
+
expect(err).toBeNull()
|
|
99
|
+
expect(n).toBe(3)
|
|
100
|
+
expect(Buffer.from(first.chunks).toString('utf8')).toBe('abc')
|
|
101
|
+
expect(Buffer.from(second.chunks).toString('utf8')).toBe('abc')
|
|
102
|
+
})
|
|
103
|
+
|
|
104
|
+
test('MultiWriter awaits async generated writers', async () => {
|
|
105
|
+
const chunks: number[] = []
|
|
106
|
+
const writer = MultiWriter({
|
|
107
|
+
async Write(p: $.Bytes): Promise<[number, $.GoError]> {
|
|
108
|
+
await Promise.resolve()
|
|
109
|
+
chunks.push(...Array.from(p ?? []))
|
|
110
|
+
return [$.len(p), null]
|
|
111
|
+
},
|
|
112
|
+
})
|
|
113
|
+
|
|
114
|
+
const [n, err] = await writer.Write($.stringToBytes('abc'))
|
|
115
|
+
|
|
116
|
+
expect(err).toBeNull()
|
|
117
|
+
expect(n).toBe(3)
|
|
118
|
+
expect(Buffer.from(chunks).toString('utf8')).toBe('abc')
|
|
119
|
+
})
|
|
120
|
+
|
|
121
|
+
test('PipeReader waits for a later write', async () => {
|
|
122
|
+
const [reader, writer] = Pipe()
|
|
123
|
+
const buf = new Uint8Array(5)
|
|
124
|
+
|
|
125
|
+
const read = reader.Read(buf)
|
|
126
|
+
const [written, writeErr] = await writer.Write($.stringToBytes('later'))
|
|
127
|
+
const [readBytes, readErr] = await read
|
|
128
|
+
|
|
129
|
+
expect(writeErr).toBeNull()
|
|
130
|
+
expect(written).toBe(5)
|
|
131
|
+
expect(readErr).toBeNull()
|
|
132
|
+
expect(readBytes).toBe(5)
|
|
133
|
+
expect(Buffer.from(buf).toString('utf8')).toBe('later')
|
|
134
|
+
})
|
|
135
|
+
})
|
package/gs/io/io.ts
CHANGED
|
@@ -72,67 +72,111 @@ export interface WriteSeeker extends Writer, Seeker {}
|
|
|
72
72
|
export interface ReadWriteSeeker extends Reader, Writer, Seeker {}
|
|
73
73
|
|
|
74
74
|
class pipeState {
|
|
75
|
-
private chunks: Uint8Array[] = []
|
|
76
|
-
private readOffset = 0
|
|
77
75
|
private readerClosed = false
|
|
78
76
|
private writerClosed = false
|
|
79
77
|
private readerErr: $.GoError = null
|
|
80
78
|
private writerErr: $.GoError = null
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
79
|
+
private pendingReads: Array<{
|
|
80
|
+
data: $.Bytes
|
|
81
|
+
resolve: (result: [number, $.GoError]) => void
|
|
82
|
+
}> = []
|
|
83
|
+
private pendingWrites: Array<{
|
|
84
|
+
data: Uint8Array
|
|
85
|
+
offset: number
|
|
86
|
+
resolve: (result: [number, $.GoError]) => void
|
|
87
|
+
}> = []
|
|
88
|
+
|
|
89
|
+
Read(p: $.Bytes): Promise<[number, $.GoError]> {
|
|
90
|
+
return (async (): Promise<[number, $.GoError]> => {
|
|
91
|
+
if (this.readerClosed) {
|
|
92
|
+
return [0, this.readerErr ?? ErrClosedPipe]
|
|
93
|
+
}
|
|
94
|
+
if ($.len(p) === 0) {
|
|
95
|
+
return [0, null]
|
|
96
|
+
}
|
|
97
|
+
if (this.pendingWrites.length > 0) {
|
|
98
|
+
return this.consumeNextWrite(p)
|
|
99
|
+
}
|
|
90
100
|
if (this.writerClosed) {
|
|
91
101
|
return [0, this.writerErr ?? EOF]
|
|
92
102
|
}
|
|
93
|
-
return [
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
while (copied < $.len(p) && this.chunks.length > 0) {
|
|
98
|
-
const chunk = this.chunks[0]
|
|
99
|
-
const available = chunk.length - this.readOffset
|
|
100
|
-
const want = Math.min($.len(p) - copied, available)
|
|
101
|
-
const target = $.goSlice(p, copied, copied + want)
|
|
102
|
-
$.copy(target, chunk.subarray(this.readOffset, this.readOffset + want))
|
|
103
|
-
copied += want
|
|
104
|
-
this.readOffset += want
|
|
105
|
-
if (this.readOffset === chunk.length) {
|
|
106
|
-
this.chunks.shift()
|
|
107
|
-
this.readOffset = 0
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
return [copied, null]
|
|
103
|
+
return await new Promise<[number, $.GoError]>((resolve) => {
|
|
104
|
+
this.pendingReads.push({ data: p, resolve })
|
|
105
|
+
})
|
|
106
|
+
})()
|
|
111
107
|
}
|
|
112
108
|
|
|
113
|
-
Write(p: $.Bytes): [number, $.GoError] {
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
109
|
+
Write(p: $.Bytes): Promise<[number, $.GoError]> {
|
|
110
|
+
return (async (): Promise<[number, $.GoError]> => {
|
|
111
|
+
if (this.writerClosed || this.readerClosed) {
|
|
112
|
+
return [0, this.readerErr ?? ErrClosedPipe]
|
|
113
|
+
}
|
|
114
|
+
if ($.len(p) === 0) {
|
|
115
|
+
return [0, null]
|
|
116
|
+
}
|
|
117
|
+
const data = new Uint8Array($.len(p))
|
|
118
|
+
$.copy(data, p)
|
|
119
|
+
return await new Promise<[number, $.GoError]>((resolve) => {
|
|
120
|
+
this.pendingWrites.push({ data, offset: 0, resolve })
|
|
121
|
+
this.drain()
|
|
122
|
+
})
|
|
123
|
+
})()
|
|
121
124
|
}
|
|
122
125
|
|
|
123
126
|
CloseReader(err: $.GoError): $.GoError {
|
|
124
127
|
this.readerClosed = true
|
|
125
128
|
this.readerErr = err
|
|
126
|
-
this.
|
|
127
|
-
this.
|
|
129
|
+
this.resolvePendingReads(ErrClosedPipe)
|
|
130
|
+
this.resolvePendingWrites(ErrClosedPipe)
|
|
128
131
|
return null
|
|
129
132
|
}
|
|
130
133
|
|
|
131
134
|
CloseWriter(err: $.GoError): $.GoError {
|
|
132
135
|
this.writerClosed = true
|
|
133
136
|
this.writerErr = err
|
|
137
|
+
if (this.pendingWrites.length === 0) {
|
|
138
|
+
this.resolvePendingReads(err ?? EOF)
|
|
139
|
+
}
|
|
134
140
|
return null
|
|
135
141
|
}
|
|
142
|
+
|
|
143
|
+
private drain(): void {
|
|
144
|
+
while (this.pendingWrites.length > 0 && this.pendingReads.length > 0) {
|
|
145
|
+
if (this.readerClosed) {
|
|
146
|
+
this.resolvePendingWrites(this.readerErr ?? ErrClosedPipe)
|
|
147
|
+
return
|
|
148
|
+
}
|
|
149
|
+
const pending = this.pendingReads.shift()!
|
|
150
|
+
pending.resolve(this.consumeNextWrite(pending.data))
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
private consumeNextWrite(p: $.Bytes): [number, $.GoError] {
|
|
155
|
+
const pending = this.pendingWrites[0]
|
|
156
|
+
const n = Math.min($.len(p), pending.data.length - pending.offset)
|
|
157
|
+
$.copy(p, pending.data.subarray(pending.offset, pending.offset + n))
|
|
158
|
+
pending.offset += n
|
|
159
|
+
if (pending.offset === pending.data.length) {
|
|
160
|
+
this.pendingWrites.shift()
|
|
161
|
+
pending.resolve([pending.data.length, null])
|
|
162
|
+
if (this.writerClosed && this.pendingWrites.length === 0) {
|
|
163
|
+
this.resolvePendingReads(this.writerErr ?? EOF)
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
return [n, null]
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
private resolvePendingReads(err: $.GoError): void {
|
|
170
|
+
while (this.pendingReads.length > 0) {
|
|
171
|
+
this.pendingReads.shift()!.resolve([0, err])
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
private resolvePendingWrites(err: $.GoError): void {
|
|
176
|
+
while (this.pendingWrites.length > 0) {
|
|
177
|
+
this.pendingWrites.shift()!.resolve([0, err])
|
|
178
|
+
}
|
|
179
|
+
}
|
|
136
180
|
}
|
|
137
181
|
|
|
138
182
|
// PipeReader is the read half of a pipe.
|
|
@@ -140,7 +184,7 @@ export class PipeReader implements Reader, Closer {
|
|
|
140
184
|
constructor(private pipe: pipeState) {}
|
|
141
185
|
|
|
142
186
|
Read(data: $.Bytes): [number, $.GoError] {
|
|
143
|
-
return this.pipe.Read(data)
|
|
187
|
+
return this.pipe.Read(data) as any
|
|
144
188
|
}
|
|
145
189
|
|
|
146
190
|
Close(): $.GoError {
|
|
@@ -157,7 +201,7 @@ export class PipeWriter implements Writer, Closer {
|
|
|
157
201
|
constructor(private pipe: pipeState) {}
|
|
158
202
|
|
|
159
203
|
Write(data: $.Bytes): [number, $.GoError] {
|
|
160
|
-
return this.pipe.Write(data)
|
|
204
|
+
return this.pipe.Write(data) as any
|
|
161
205
|
}
|
|
162
206
|
|
|
163
207
|
Close(): $.GoError {
|
|
@@ -232,28 +276,40 @@ class DiscardWriter implements Writer {
|
|
|
232
276
|
}
|
|
233
277
|
}
|
|
234
278
|
|
|
235
|
-
export const Discard: Writer = new DiscardWriter()
|
|
279
|
+
export const Discard: Writer | null = new DiscardWriter()
|
|
236
280
|
|
|
237
281
|
// WriteString writes the contents of the string s to w, which accepts a slice of bytes
|
|
238
|
-
export function WriteString(
|
|
282
|
+
export async function WriteString(
|
|
283
|
+
w: Writer,
|
|
284
|
+
s: string,
|
|
285
|
+
): Promise<[number, $.GoError]> {
|
|
239
286
|
// Check if w implements StringWriter interface
|
|
240
287
|
if ('WriteString' in w && typeof (w as any).WriteString === 'function') {
|
|
241
|
-
return (w as StringWriter).WriteString(s)
|
|
288
|
+
return await ((w as StringWriter).WriteString(s) as any)
|
|
242
289
|
}
|
|
243
290
|
|
|
244
291
|
// Convert string to bytes and write
|
|
245
292
|
const bytes = new TextEncoder().encode(s)
|
|
246
|
-
return w.Write(bytes)
|
|
293
|
+
return await (w.Write(bytes) as any)
|
|
247
294
|
}
|
|
248
295
|
|
|
249
296
|
// LimitedReader reads from R but limits the amount of data returned to just N bytes
|
|
250
297
|
export class LimitedReader implements Reader {
|
|
251
|
-
public R: Reader
|
|
298
|
+
public R: Reader | null
|
|
252
299
|
public N: number
|
|
253
300
|
|
|
254
|
-
constructor(
|
|
255
|
-
|
|
256
|
-
|
|
301
|
+
constructor(
|
|
302
|
+
r?: Reader | { R?: Reader | null; N?: number } | null,
|
|
303
|
+
n?: number,
|
|
304
|
+
) {
|
|
305
|
+
if (r != null && typeof (r as { Read?: unknown }).Read !== 'function') {
|
|
306
|
+
const init = r as { R?: Reader | null; N?: number }
|
|
307
|
+
this.R = init.R ?? null
|
|
308
|
+
this.N = init.N ?? 0
|
|
309
|
+
return
|
|
310
|
+
}
|
|
311
|
+
this.R = (r as Reader | null | undefined) ?? null
|
|
312
|
+
this.N = n ?? 0
|
|
257
313
|
}
|
|
258
314
|
|
|
259
315
|
Read(p: $.Bytes): [number, $.GoError] {
|
|
@@ -261,6 +317,9 @@ export class LimitedReader implements Reader {
|
|
|
261
317
|
if (this.N <= 0) {
|
|
262
318
|
return [0, EOF]
|
|
263
319
|
}
|
|
320
|
+
if (this.R == null) {
|
|
321
|
+
throw new Error('io.LimitedReader: nil reader')
|
|
322
|
+
}
|
|
264
323
|
|
|
265
324
|
let readBuf = p
|
|
266
325
|
if ($.len(p) > this.N) {
|
|
@@ -596,7 +655,15 @@ export async function ReadAll(r: Reader): Promise<[$.Bytes, $.GoError]> {
|
|
|
596
655
|
}
|
|
597
656
|
|
|
598
657
|
// NopCloser returns a ReadCloser with a no-op Close method wrapping the provided Reader r
|
|
599
|
-
export function NopCloser(r: Reader): ReadCloser {
|
|
658
|
+
export function NopCloser(r: Reader | null): ReadCloser {
|
|
659
|
+
if (r == null) {
|
|
660
|
+
return {
|
|
661
|
+
Read: () => {
|
|
662
|
+
throw new Error('nil Reader')
|
|
663
|
+
},
|
|
664
|
+
Close: () => null,
|
|
665
|
+
}
|
|
666
|
+
}
|
|
600
667
|
return {
|
|
601
668
|
Read: r.Read.bind(r),
|
|
602
669
|
Close: () => null,
|
|
@@ -645,20 +712,23 @@ class multiReader implements Reader {
|
|
|
645
712
|
}
|
|
646
713
|
|
|
647
714
|
// MultiWriter creates a writer that duplicates its writes to all the provided writers
|
|
648
|
-
export function MultiWriter(...writers: Writer[]): Writer {
|
|
649
|
-
return new multiWriter(writers.slice())
|
|
715
|
+
export function MultiWriter(...writers: (Writer | null)[]): Writer {
|
|
716
|
+
return new multiWriter(writers.slice()) as any
|
|
650
717
|
}
|
|
651
718
|
|
|
652
|
-
class multiWriter
|
|
653
|
-
private writers: Writer[]
|
|
719
|
+
class multiWriter {
|
|
720
|
+
private writers: (Writer | null)[]
|
|
654
721
|
|
|
655
|
-
constructor(writers: Writer[]) {
|
|
722
|
+
constructor(writers: (Writer | null)[]) {
|
|
656
723
|
this.writers = writers
|
|
657
724
|
}
|
|
658
725
|
|
|
659
|
-
Write(p: $.Bytes): [number, $.GoError] {
|
|
726
|
+
async Write(p: $.Bytes): Promise<[number, $.GoError]> {
|
|
660
727
|
for (const w of this.writers) {
|
|
661
|
-
|
|
728
|
+
if (w == null) {
|
|
729
|
+
throw new Error('io.MultiWriter: nil writer')
|
|
730
|
+
}
|
|
731
|
+
const [n, err] = await w.Write(p)
|
|
662
732
|
if (err !== null) {
|
|
663
733
|
return [n, err]
|
|
664
734
|
}
|
|
@@ -671,23 +741,33 @@ class multiWriter implements Writer {
|
|
|
671
741
|
}
|
|
672
742
|
|
|
673
743
|
// TeeReader returns a Reader that writes to w what it reads from r
|
|
674
|
-
export function TeeReader(r: Reader, w: Writer): Reader {
|
|
744
|
+
export function TeeReader(r: Reader | null, w: Writer | null): Reader {
|
|
675
745
|
return new teeReader(r, w)
|
|
676
746
|
}
|
|
677
747
|
|
|
678
748
|
class teeReader implements Reader {
|
|
679
|
-
private r: Reader
|
|
680
|
-
private w: Writer
|
|
749
|
+
private r: Reader | null
|
|
750
|
+
private w: Writer | null
|
|
681
751
|
|
|
682
|
-
constructor(r: Reader, w: Writer) {
|
|
752
|
+
constructor(r: Reader | null, w: Writer | null) {
|
|
683
753
|
this.r = r
|
|
684
754
|
this.w = w
|
|
685
755
|
}
|
|
686
756
|
|
|
687
757
|
Read(p: $.Bytes): [number, $.GoError] {
|
|
688
|
-
|
|
758
|
+
return this.read(p) as any
|
|
759
|
+
}
|
|
760
|
+
|
|
761
|
+
private async read(p: $.Bytes): Promise<[number, $.GoError]> {
|
|
762
|
+
if (this.r == null) {
|
|
763
|
+
throw new Error('io.TeeReader: nil reader')
|
|
764
|
+
}
|
|
765
|
+
const [n, err] = await this.r.Read(p)
|
|
689
766
|
if (n > 0) {
|
|
690
|
-
|
|
767
|
+
if (this.w == null) {
|
|
768
|
+
throw new Error('io.TeeReader: nil writer')
|
|
769
|
+
}
|
|
770
|
+
const [nw, ew] = await this.w.Write($.goSlice(p, 0, n))
|
|
691
771
|
if (ew !== null) {
|
|
692
772
|
return [n, ew]
|
|
693
773
|
}
|
package/gs/io/meta.json
CHANGED
package/gs/math/bits/index.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// This replaces the auto-generated version that has TypeScript syntax errors
|
|
3
3
|
|
|
4
4
|
// UintSize is the size of a uint in bits
|
|
5
|
-
export const UintSize =
|
|
5
|
+
export const UintSize = 64
|
|
6
6
|
|
|
7
7
|
type Word64 = number | bigint
|
|
8
8
|
|
|
@@ -23,8 +23,8 @@ function word64Result(value: bigint, useBigInt: boolean): Word64 {
|
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
// --- Leading zeros ---
|
|
26
|
-
export function LeadingZeros(x:
|
|
27
|
-
return
|
|
26
|
+
export function LeadingZeros(x: Word64): number {
|
|
27
|
+
return LeadingZeros64(x)
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
export function LeadingZeros8(x: number): number {
|
|
@@ -53,9 +53,8 @@ export function LeadingZeros64(x: Word64): number {
|
|
|
53
53
|
}
|
|
54
54
|
|
|
55
55
|
// --- Trailing zeros ---
|
|
56
|
-
export function TrailingZeros(x:
|
|
57
|
-
|
|
58
|
-
return TrailingZeros32(x)
|
|
56
|
+
export function TrailingZeros(x: Word64): number {
|
|
57
|
+
return TrailingZeros64(x)
|
|
59
58
|
}
|
|
60
59
|
|
|
61
60
|
export function TrailingZeros8(x: number): number {
|
|
@@ -90,8 +89,8 @@ export function TrailingZeros64(x: Word64): number {
|
|
|
90
89
|
}
|
|
91
90
|
|
|
92
91
|
// --- Ones count ---
|
|
93
|
-
export function OnesCount(x:
|
|
94
|
-
return
|
|
92
|
+
export function OnesCount(x: Word64): number {
|
|
93
|
+
return OnesCount64(x)
|
|
95
94
|
}
|
|
96
95
|
|
|
97
96
|
export function OnesCount8(x: number): number {
|
|
@@ -124,8 +123,11 @@ export function OnesCount64(x: Word64): number {
|
|
|
124
123
|
}
|
|
125
124
|
|
|
126
125
|
// --- Rotate left ---
|
|
127
|
-
export function RotateLeft(x: number, k: number): number
|
|
128
|
-
|
|
126
|
+
export function RotateLeft(x: number, k: number): number
|
|
127
|
+
export function RotateLeft(x: bigint, k: number): bigint
|
|
128
|
+
export function RotateLeft(x: Word64, k: number): number
|
|
129
|
+
export function RotateLeft(x: Word64, k: number): Word64 {
|
|
130
|
+
return RotateLeft64(x, k)
|
|
129
131
|
}
|
|
130
132
|
|
|
131
133
|
export function RotateLeft8(x: number, k: number): number {
|
|
@@ -151,6 +153,7 @@ export function RotateLeft32(x: number, k: number): number {
|
|
|
151
153
|
|
|
152
154
|
export function RotateLeft64(x: number, k: number): number
|
|
153
155
|
export function RotateLeft64(x: bigint, k: number): bigint
|
|
156
|
+
export function RotateLeft64(x: Word64, k: number): number
|
|
154
157
|
export function RotateLeft64(x: Word64, k: number): Word64 {
|
|
155
158
|
const n = 64
|
|
156
159
|
k = k % n
|
|
@@ -163,8 +166,11 @@ export function RotateLeft64(x: Word64, k: number): Word64 {
|
|
|
163
166
|
}
|
|
164
167
|
|
|
165
168
|
// --- Reverse ---
|
|
166
|
-
export function Reverse(x: number): number
|
|
167
|
-
|
|
169
|
+
export function Reverse(x: number): number
|
|
170
|
+
export function Reverse(x: bigint): bigint
|
|
171
|
+
export function Reverse(x: Word64): number
|
|
172
|
+
export function Reverse(x: Word64): Word64 {
|
|
173
|
+
return Reverse64(x)
|
|
168
174
|
}
|
|
169
175
|
|
|
170
176
|
export function Reverse8(x: number): number {
|
|
@@ -196,6 +202,7 @@ export function Reverse32(x: number): number {
|
|
|
196
202
|
|
|
197
203
|
export function Reverse64(x: number): number
|
|
198
204
|
export function Reverse64(x: bigint): bigint
|
|
205
|
+
export function Reverse64(x: Word64): number
|
|
199
206
|
export function Reverse64(x: Word64): Word64 {
|
|
200
207
|
// Implement 64-bit reverse using similar bit manipulation
|
|
201
208
|
const useBigInt = useBigIntResult(x)
|
|
@@ -226,8 +233,11 @@ export function Reverse64(x: Word64): Word64 {
|
|
|
226
233
|
}
|
|
227
234
|
|
|
228
235
|
// --- ReverseBytes ---
|
|
229
|
-
export function ReverseBytes(x: number): number
|
|
230
|
-
|
|
236
|
+
export function ReverseBytes(x: number): number
|
|
237
|
+
export function ReverseBytes(x: bigint): bigint
|
|
238
|
+
export function ReverseBytes(x: Word64): number
|
|
239
|
+
export function ReverseBytes(x: Word64): Word64 {
|
|
240
|
+
return ReverseBytes64(x)
|
|
231
241
|
}
|
|
232
242
|
|
|
233
243
|
export function ReverseBytes16(x: number): number {
|
|
@@ -247,6 +257,7 @@ export function ReverseBytes32(x: number): number {
|
|
|
247
257
|
|
|
248
258
|
export function ReverseBytes64(x: number): number
|
|
249
259
|
export function ReverseBytes64(x: bigint): bigint
|
|
260
|
+
export function ReverseBytes64(x: Word64): number
|
|
250
261
|
export function ReverseBytes64(x: Word64): Word64 {
|
|
251
262
|
const useBigInt = useBigIntResult(x)
|
|
252
263
|
const word = toUint64(x)
|
|
@@ -266,8 +277,8 @@ export function ReverseBytes64(x: Word64): Word64 {
|
|
|
266
277
|
}
|
|
267
278
|
|
|
268
279
|
// --- Len ---
|
|
269
|
-
export function Len(x:
|
|
270
|
-
return
|
|
280
|
+
export function Len(x: Word64): number {
|
|
281
|
+
return Len64(x)
|
|
271
282
|
}
|
|
272
283
|
|
|
273
284
|
export function Len8(x: number): number {
|
|
@@ -287,8 +298,11 @@ export function Len64(x: Word64): number {
|
|
|
287
298
|
}
|
|
288
299
|
|
|
289
300
|
// --- Multiplication functions ---
|
|
290
|
-
export function Mul(x: number, y: number): [number, number]
|
|
291
|
-
|
|
301
|
+
export function Mul(x: number, y: number): [number, number]
|
|
302
|
+
export function Mul(x: bigint, y: bigint): [bigint, bigint]
|
|
303
|
+
export function Mul(x: Word64, y: Word64): [number, number]
|
|
304
|
+
export function Mul(x: Word64, y: Word64): [Word64, Word64] {
|
|
305
|
+
return Mul64(x, y)
|
|
292
306
|
}
|
|
293
307
|
|
|
294
308
|
export function Mul32(x: number, y: number): [number, number] {
|
|
@@ -301,6 +315,7 @@ export function Mul32(x: number, y: number): [number, number] {
|
|
|
301
315
|
|
|
302
316
|
export function Mul64(x: number, y: number): [number, number]
|
|
303
317
|
export function Mul64(x: bigint, y: bigint): [bigint, bigint]
|
|
318
|
+
export function Mul64(x: Word64, y: Word64): [number, number]
|
|
304
319
|
export function Mul64(x: Word64, y: Word64): [Word64, Word64] {
|
|
305
320
|
const useBigInt = useBigIntResult(x, y)
|
|
306
321
|
x = toUint64(x)
|
|
@@ -309,15 +324,15 @@ export function Mul64(x: Word64, y: Word64): [Word64, Word64] {
|
|
|
309
324
|
const lo = product & uint64Mask
|
|
310
325
|
const hi = product >> 64n
|
|
311
326
|
|
|
312
|
-
return [
|
|
313
|
-
word64Result(hi & uint64Mask, useBigInt),
|
|
314
|
-
word64Result(lo, useBigInt),
|
|
315
|
-
]
|
|
327
|
+
return [word64Result(hi & uint64Mask, useBigInt), word64Result(lo, useBigInt)]
|
|
316
328
|
}
|
|
317
329
|
|
|
318
330
|
// --- Division functions ---
|
|
319
|
-
export function Div(hi: number, lo: number, y: number): [number, number]
|
|
320
|
-
|
|
331
|
+
export function Div(hi: number, lo: number, y: number): [number, number]
|
|
332
|
+
export function Div(hi: bigint, lo: bigint, y: bigint): [bigint, bigint]
|
|
333
|
+
export function Div(hi: Word64, lo: Word64, y: Word64): [number, number]
|
|
334
|
+
export function Div(hi: Word64, lo: Word64, y: Word64): [Word64, Word64] {
|
|
335
|
+
return Div64(hi, lo, y)
|
|
321
336
|
}
|
|
322
337
|
|
|
323
338
|
export function Div32(hi: number, lo: number, y: number): [number, number] {
|
|
@@ -337,6 +352,7 @@ export function Div32(hi: number, lo: number, y: number): [number, number] {
|
|
|
337
352
|
|
|
338
353
|
export function Div64(hi: number, lo: number, y: number): [number, number]
|
|
339
354
|
export function Div64(hi: bigint, lo: bigint, y: bigint): [bigint, bigint]
|
|
355
|
+
export function Div64(hi: Word64, lo: Word64, y: Word64): [number, number]
|
|
340
356
|
export function Div64(hi: Word64, lo: Word64, y: Word64): [Word64, Word64] {
|
|
341
357
|
const useBigInt = useBigIntResult(hi, lo, y)
|
|
342
358
|
hi = toUint64(hi)
|
|
@@ -356,8 +372,11 @@ export function Div64(hi: Word64, lo: Word64, y: Word64): [Word64, Word64] {
|
|
|
356
372
|
}
|
|
357
373
|
|
|
358
374
|
// --- Add and Sub with carry ---
|
|
359
|
-
export function Add(x: number, y: number, carry: number): [number, number]
|
|
360
|
-
|
|
375
|
+
export function Add(x: number, y: number, carry: number): [number, number]
|
|
376
|
+
export function Add(x: bigint, y: bigint, carry: bigint): [bigint, bigint]
|
|
377
|
+
export function Add(x: Word64, y: Word64, carry: Word64): [number, number]
|
|
378
|
+
export function Add(x: Word64, y: Word64, carry: Word64): [Word64, Word64] {
|
|
379
|
+
return Add64(x, y, carry)
|
|
361
380
|
}
|
|
362
381
|
|
|
363
382
|
export function Add32(x: number, y: number, carry: number): [number, number] {
|
|
@@ -369,6 +388,7 @@ export function Add32(x: number, y: number, carry: number): [number, number] {
|
|
|
369
388
|
|
|
370
389
|
export function Add64(x: number, y: number, carry: number): [number, number]
|
|
371
390
|
export function Add64(x: bigint, y: bigint, carry: bigint): [bigint, bigint]
|
|
391
|
+
export function Add64(x: Word64, y: Word64, carry: Word64): [number, number]
|
|
372
392
|
export function Add64(x: Word64, y: Word64, carry: Word64): [Word64, Word64] {
|
|
373
393
|
const useBigInt = useBigIntResult(x, y, carry)
|
|
374
394
|
const sum = toUint64(x) + toUint64(y) + toUint64(carry)
|
|
@@ -377,8 +397,11 @@ export function Add64(x: Word64, y: Word64, carry: Word64): [Word64, Word64] {
|
|
|
377
397
|
return [word64Result(result, useBigInt), word64Result(carryOut, useBigInt)]
|
|
378
398
|
}
|
|
379
399
|
|
|
380
|
-
export function Sub(x: number, y: number, borrow: number): [number, number]
|
|
381
|
-
|
|
400
|
+
export function Sub(x: number, y: number, borrow: number): [number, number]
|
|
401
|
+
export function Sub(x: bigint, y: bigint, borrow: bigint): [bigint, bigint]
|
|
402
|
+
export function Sub(x: Word64, y: Word64, borrow: Word64): [number, number]
|
|
403
|
+
export function Sub(x: Word64, y: Word64, borrow: Word64): [Word64, Word64] {
|
|
404
|
+
return Sub64(x, y, borrow)
|
|
382
405
|
}
|
|
383
406
|
|
|
384
407
|
export function Sub32(x: number, y: number, borrow: number): [number, number] {
|
|
@@ -390,6 +413,7 @@ export function Sub32(x: number, y: number, borrow: number): [number, number] {
|
|
|
390
413
|
|
|
391
414
|
export function Sub64(x: number, y: number, borrow: number): [number, number]
|
|
392
415
|
export function Sub64(x: bigint, y: bigint, borrow: bigint): [bigint, bigint]
|
|
416
|
+
export function Sub64(x: Word64, y: Word64, borrow: Word64): [number, number]
|
|
393
417
|
export function Sub64(x: Word64, y: Word64, borrow: Word64): [Word64, Word64] {
|
|
394
418
|
const useBigInt = useBigIntResult(x, y, borrow)
|
|
395
419
|
const diff = toUint64(x) - toUint64(y) - toUint64(borrow)
|