goscript 0.0.25 → 0.0.28
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/README.md +4 -4
- package/cmd/goscript/cmd_compile.go +0 -3
- package/cmd/goscript/deps.go +11 -0
- package/compiler/analysis.go +259 -55
- package/compiler/assignment.go +2 -2
- package/compiler/builtin_test.go +1 -1
- package/compiler/compiler.go +201 -49
- package/compiler/compiler_test.go +53 -0
- package/compiler/composite-lit.go +32 -8
- package/compiler/decl.go +6 -6
- package/compiler/expr-call.go +83 -0
- package/compiler/expr.go +1 -1
- package/compiler/protobuf.go +557 -0
- package/compiler/spec-struct.go +4 -0
- package/compiler/spec-value.go +11 -3
- package/compiler/spec.go +18 -1
- package/compiler/stmt-assign.go +35 -0
- package/compiler/type-assert.go +87 -0
- package/compiler/type.go +5 -2
- package/dist/gs/builtin/builtin.d.ts +19 -1
- package/dist/gs/builtin/builtin.js +85 -5
- package/dist/gs/builtin/builtin.js.map +1 -1
- package/dist/gs/builtin/channel.js.map +1 -1
- package/dist/gs/builtin/slice.d.ts +1 -1
- package/dist/gs/builtin/slice.js +59 -26
- package/dist/gs/builtin/slice.js.map +1 -1
- package/dist/gs/cmp/index.js.map +1 -1
- package/dist/gs/context/context.d.ts +1 -1
- package/dist/gs/context/context.js +20 -11
- package/dist/gs/context/context.js.map +1 -1
- package/dist/gs/errors/errors.d.ts +7 -0
- package/dist/gs/errors/errors.js +190 -0
- package/dist/gs/errors/errors.js.map +1 -0
- package/dist/gs/errors/index.d.ts +1 -0
- package/dist/gs/errors/index.js +2 -0
- package/dist/gs/errors/index.js.map +1 -0
- package/dist/gs/internal/goarch/index.js +1 -1
- package/dist/gs/internal/goarch/index.js.map +1 -1
- package/dist/gs/io/index.d.ts +1 -0
- package/dist/gs/io/index.js +2 -0
- package/dist/gs/io/index.js.map +1 -0
- package/dist/gs/io/io.d.ts +107 -0
- package/dist/gs/io/io.js +385 -0
- package/dist/gs/io/io.js.map +1 -0
- package/dist/gs/iter/iter.js.map +1 -1
- package/dist/gs/math/bits/index.js +34 -32
- package/dist/gs/math/bits/index.js.map +1 -1
- package/dist/gs/runtime/runtime.d.ts +1 -0
- package/dist/gs/runtime/runtime.js +15 -18
- package/dist/gs/runtime/runtime.js.map +1 -1
- package/dist/gs/slices/slices.d.ts +1 -1
- package/dist/gs/slices/slices.js +1 -1
- package/dist/gs/slices/slices.js.map +1 -1
- package/dist/gs/strings/builder.d.ts +18 -0
- package/dist/gs/strings/builder.js +205 -0
- package/dist/gs/strings/builder.js.map +1 -0
- package/dist/gs/strings/clone.d.ts +1 -0
- package/dist/gs/strings/clone.js +16 -0
- package/dist/gs/strings/clone.js.map +1 -0
- package/dist/gs/strings/compare.d.ts +1 -0
- package/dist/gs/strings/compare.js +14 -0
- package/dist/gs/strings/compare.js.map +1 -0
- package/dist/gs/strings/index.d.ts +2 -0
- package/dist/gs/strings/index.js +3 -0
- package/dist/gs/strings/index.js.map +1 -0
- package/dist/gs/strings/iter.d.ts +8 -0
- package/dist/gs/strings/iter.js +160 -0
- package/dist/gs/strings/iter.js.map +1 -0
- package/dist/gs/strings/reader.d.ts +34 -0
- package/dist/gs/strings/reader.js +418 -0
- package/dist/gs/strings/reader.js.map +1 -0
- package/dist/gs/strings/replace.d.ts +106 -0
- package/dist/gs/strings/replace.js +1136 -0
- package/dist/gs/strings/replace.js.map +1 -0
- package/dist/gs/strings/search.d.ts +24 -0
- package/dist/gs/strings/search.js +169 -0
- package/dist/gs/strings/search.js.map +1 -0
- package/dist/gs/strings/strings.d.ts +47 -0
- package/dist/gs/strings/strings.js +418 -0
- package/dist/gs/strings/strings.js.map +1 -0
- package/dist/gs/stringslite/index.d.ts +1 -0
- package/dist/gs/stringslite/index.js +2 -0
- package/dist/gs/stringslite/index.js.map +1 -0
- package/dist/gs/stringslite/strings.d.ts +11 -0
- package/dist/gs/stringslite/strings.js +67 -0
- package/dist/gs/stringslite/strings.js.map +1 -0
- package/dist/gs/sync/index.d.ts +1 -0
- package/dist/gs/sync/index.js +2 -0
- package/dist/gs/sync/index.js.map +1 -0
- package/dist/gs/sync/sync.d.ts +79 -0
- package/dist/gs/sync/sync.js +392 -0
- package/dist/gs/sync/sync.js.map +1 -0
- package/dist/gs/time/time.js +7 -7
- package/dist/gs/time/time.js.map +1 -1
- package/dist/gs/unicode/index.d.ts +1 -0
- package/dist/gs/unicode/index.js +2 -0
- package/dist/gs/unicode/index.js.map +1 -0
- package/dist/gs/unicode/unicode.d.ts +105 -0
- package/dist/gs/unicode/unicode.js +332 -0
- package/dist/gs/unicode/unicode.js.map +1 -0
- package/dist/gs/unicode/utf8/index.d.ts +1 -0
- package/dist/gs/unicode/utf8/index.js +3 -0
- package/dist/gs/unicode/utf8/index.js.map +1 -0
- package/dist/gs/unicode/utf8/utf8.d.ts +20 -0
- package/dist/gs/unicode/utf8/utf8.js +196 -0
- package/dist/gs/unicode/utf8/utf8.js.map +1 -0
- package/dist/gs/unsafe/index.d.ts +1 -0
- package/dist/gs/unsafe/index.js +2 -0
- package/dist/gs/unsafe/index.js.map +1 -0
- package/dist/gs/unsafe/unsafe.d.ts +11 -0
- package/dist/gs/unsafe/unsafe.js +44 -0
- package/dist/gs/unsafe/unsafe.js.map +1 -0
- package/go.mod +2 -1
- package/go.sum +6 -2
- package/gs/README.md +6 -0
- package/gs/builtin/builtin.ts +158 -0
- package/gs/builtin/channel.ts +683 -0
- package/gs/builtin/defer.ts +58 -0
- package/gs/builtin/index.ts +1 -0
- package/gs/builtin/io.ts +22 -0
- package/gs/builtin/map.ts +50 -0
- package/gs/builtin/slice.ts +1030 -0
- package/gs/builtin/type.ts +1106 -0
- package/gs/builtin/varRef.ts +25 -0
- package/gs/cmp/godoc.txt +8 -0
- package/gs/cmp/index.ts +29 -0
- package/gs/context/context.ts +401 -0
- package/gs/context/godoc.txt +69 -0
- package/gs/context/index.ts +1 -0
- package/gs/errors/errors.ts +223 -0
- package/gs/errors/godoc.txt +63 -0
- package/gs/errors/index.ts +1 -0
- package/gs/internal/goarch/godoc.txt +39 -0
- package/gs/internal/goarch/index.ts +18 -0
- package/gs/io/godoc.txt +61 -0
- package/gs/io/index.ts +1 -0
- package/gs/io/io.go +75 -0
- package/gs/io/io.ts +546 -0
- package/gs/iter/godoc.txt +203 -0
- package/gs/iter/index.ts +1 -0
- package/gs/iter/iter.ts +117 -0
- package/gs/math/bits/index.ts +356 -0
- package/gs/math/godoc.txt +76 -0
- package/gs/runtime/godoc.txt +331 -0
- package/gs/runtime/index.ts +1 -0
- package/gs/runtime/runtime.ts +178 -0
- package/gs/slices/godoc.txt +44 -0
- package/gs/slices/index.ts +1 -0
- package/gs/slices/slices.ts +22 -0
- package/gs/strings/builder.test.ts +121 -0
- package/gs/strings/builder.ts +223 -0
- package/gs/strings/clone.test.ts +43 -0
- package/gs/strings/clone.ts +17 -0
- package/gs/strings/compare.test.ts +84 -0
- package/gs/strings/compare.ts +13 -0
- package/gs/strings/godoc.txt +66 -0
- package/gs/strings/index.ts +2 -0
- package/gs/strings/iter.test.ts +343 -0
- package/gs/strings/iter.ts +171 -0
- package/gs/strings/reader.test.ts +243 -0
- package/gs/strings/reader.ts +451 -0
- package/gs/strings/replace.test.ts +181 -0
- package/gs/strings/replace.ts +1310 -0
- package/gs/strings/search.test.ts +214 -0
- package/gs/strings/search.ts +213 -0
- package/gs/strings/strings.test.ts +477 -0
- package/gs/strings/strings.ts +510 -0
- package/gs/stringslite/godoc.txt +17 -0
- package/gs/stringslite/index.ts +1 -0
- package/gs/stringslite/strings.ts +82 -0
- package/gs/sync/godoc.txt +21 -0
- package/gs/sync/index.ts +1 -0
- package/gs/sync/sync.go +64 -0
- package/gs/sync/sync.ts +449 -0
- package/gs/time/godoc.md +116 -0
- package/gs/time/godoc.txt +116 -0
- package/gs/time/index.ts +1 -0
- package/gs/time/time.ts +272 -0
- package/gs/unicode/godoc.txt +52 -0
- package/gs/unicode/index.ts +1 -0
- package/gs/unicode/unicode.go +38 -0
- package/gs/unicode/unicode.ts +418 -0
- package/gs/unicode/utf8/godoc.txt +22 -0
- package/gs/unicode/utf8/index.ts +2 -0
- package/gs/unicode/utf8/utf8.ts +227 -0
- package/gs/unsafe/godoc.txt +19 -0
- package/gs/unsafe/index.ts +1 -0
- package/gs/unsafe/unsafe.test.ts +68 -0
- package/gs/unsafe/unsafe.ts +77 -0
- package/package.json +6 -4
package/gs/io/io.ts
ADDED
|
@@ -0,0 +1,546 @@
|
|
|
1
|
+
// Package io provides basic interfaces to I/O primitives.
|
|
2
|
+
// Its primary job is to wrap existing implementations of such primitives,
|
|
3
|
+
// such as those in package os, into shared public interfaces that abstract
|
|
4
|
+
// the functionality, plus some other related primitives.
|
|
5
|
+
|
|
6
|
+
import * as $ from '@goscript/builtin/builtin.js'
|
|
7
|
+
|
|
8
|
+
// Simple error implementation for io package
|
|
9
|
+
class IOError {
|
|
10
|
+
constructor(private message: string) {}
|
|
11
|
+
|
|
12
|
+
Error(): string {
|
|
13
|
+
return this.message
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
toString(): string {
|
|
17
|
+
return this.message
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function newError(message: string): $.GoError {
|
|
22
|
+
return new IOError(message)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Error variables
|
|
26
|
+
export const EOF = newError('EOF')
|
|
27
|
+
export const ErrClosedPipe = newError('io: read/write on closed pipe')
|
|
28
|
+
export const ErrNoProgress = newError(
|
|
29
|
+
'multiple Read calls return no data or error',
|
|
30
|
+
)
|
|
31
|
+
export const ErrShortBuffer = newError('short buffer')
|
|
32
|
+
export const ErrShortWrite = newError('short write')
|
|
33
|
+
export const ErrUnexpectedEOF = newError('unexpected EOF')
|
|
34
|
+
|
|
35
|
+
// Seek whence values
|
|
36
|
+
export const SeekStart = 0 // seek relative to the origin of the file
|
|
37
|
+
export const SeekCurrent = 1 // seek relative to the current offset
|
|
38
|
+
export const SeekEnd = 2 // seek relative to the end
|
|
39
|
+
|
|
40
|
+
// Core interfaces
|
|
41
|
+
|
|
42
|
+
// Reader is the interface that wraps the basic Read method
|
|
43
|
+
export interface Reader {
|
|
44
|
+
Read(p: Uint8Array): [number, $.GoError]
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Writer is the interface that wraps the basic Write method
|
|
48
|
+
export interface Writer {
|
|
49
|
+
Write(p: Uint8Array): [number, $.GoError]
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Closer is the interface that wraps the basic Close method
|
|
53
|
+
export interface Closer {
|
|
54
|
+
Close(): $.GoError
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Seeker is the interface that wraps the basic Seek method
|
|
58
|
+
export interface Seeker {
|
|
59
|
+
Seek(offset: number, whence: number): [number, $.GoError]
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Combined interfaces
|
|
63
|
+
export interface ReadWriter extends Reader, Writer {}
|
|
64
|
+
export interface ReadCloser extends Reader, Closer {}
|
|
65
|
+
export interface WriteCloser extends Writer, Closer {}
|
|
66
|
+
export interface ReadWriteCloser extends Reader, Writer, Closer {}
|
|
67
|
+
export interface ReadSeeker extends Reader, Seeker {}
|
|
68
|
+
export interface WriteSeeker extends Writer, Seeker {}
|
|
69
|
+
export interface ReadWriteSeeker extends Reader, Writer, Seeker {}
|
|
70
|
+
|
|
71
|
+
// ReaderAt is the interface that wraps the basic ReadAt method
|
|
72
|
+
export interface ReaderAt {
|
|
73
|
+
ReadAt(p: Uint8Array, off: number): [number, $.GoError]
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// WriterAt is the interface that wraps the basic WriteAt method
|
|
77
|
+
export interface WriterAt {
|
|
78
|
+
WriteAt(p: Uint8Array, off: number): [number, $.GoError]
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// ByteReader is the interface that wraps the ReadByte method
|
|
82
|
+
export interface ByteReader {
|
|
83
|
+
ReadByte(): [number, $.GoError]
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// ByteWriter is the interface that wraps the WriteByte method
|
|
87
|
+
export interface ByteWriter {
|
|
88
|
+
WriteByte(c: number): $.GoError
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// ByteScanner is the interface that adds the UnreadByte method to the basic ReadByte method
|
|
92
|
+
export interface ByteScanner extends ByteReader {
|
|
93
|
+
UnreadByte(): $.GoError
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// RuneReader is the interface that wraps the ReadRune method
|
|
97
|
+
export interface RuneReader {
|
|
98
|
+
ReadRune(): [number, number, $.GoError]
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// RuneScanner is the interface that adds the UnreadRune method to the basic ReadRune method
|
|
102
|
+
export interface RuneScanner extends RuneReader {
|
|
103
|
+
UnreadRune(): $.GoError
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// StringWriter is the interface that wraps the WriteString method
|
|
107
|
+
export interface StringWriter {
|
|
108
|
+
WriteString(s: string): [number, $.GoError]
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// WriterTo is the interface that wraps the WriteTo method
|
|
112
|
+
export interface WriterTo {
|
|
113
|
+
WriteTo(w: Writer): [number, $.GoError]
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// ReaderFrom is the interface that wraps the ReadFrom method
|
|
117
|
+
export interface ReaderFrom {
|
|
118
|
+
ReadFrom(r: Reader): [number, $.GoError]
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Discard is a Writer on which all Write calls succeed without doing anything
|
|
122
|
+
class DiscardWriter implements Writer {
|
|
123
|
+
Write(p: Uint8Array): [number, $.GoError] {
|
|
124
|
+
return [p.length, null]
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export const Discard: Writer = new DiscardWriter()
|
|
129
|
+
|
|
130
|
+
// WriteString writes the contents of the string s to w, which accepts a slice of bytes
|
|
131
|
+
export function WriteString(w: Writer, s: string): [number, $.GoError] {
|
|
132
|
+
// Check if w implements StringWriter interface
|
|
133
|
+
if ('WriteString' in w && typeof (w as any).WriteString === 'function') {
|
|
134
|
+
return (w as StringWriter).WriteString(s)
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// Convert string to bytes and write
|
|
138
|
+
const bytes = new TextEncoder().encode(s)
|
|
139
|
+
return w.Write(bytes)
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// LimitedReader reads from R but limits the amount of data returned to just N bytes
|
|
143
|
+
export class LimitedReader implements Reader {
|
|
144
|
+
public R: Reader
|
|
145
|
+
public N: number
|
|
146
|
+
|
|
147
|
+
constructor(r: Reader, n: number) {
|
|
148
|
+
this.R = r
|
|
149
|
+
this.N = n
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
Read(p: Uint8Array): [number, $.GoError] {
|
|
153
|
+
if (this.N <= 0) {
|
|
154
|
+
return [0, EOF]
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
let readBuf = p
|
|
158
|
+
if (p.length > this.N) {
|
|
159
|
+
readBuf = p.subarray(0, this.N)
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
const [n, err] = this.R.Read(readBuf)
|
|
163
|
+
this.N -= n
|
|
164
|
+
return [n, err]
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// LimitReader returns a Reader that reads from r but stops with EOF after n bytes
|
|
169
|
+
export function LimitReader(r: Reader, n: number): Reader {
|
|
170
|
+
return new LimitedReader(r, n)
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// SectionReader implements Read, Seek, and ReadAt on a section of an underlying ReaderAt
|
|
174
|
+
export class SectionReader implements Reader, Seeker, ReaderAt {
|
|
175
|
+
private r: ReaderAt
|
|
176
|
+
private base: number
|
|
177
|
+
private off: number
|
|
178
|
+
private limit: number
|
|
179
|
+
|
|
180
|
+
constructor(r: ReaderAt, off: number, n: number) {
|
|
181
|
+
this.r = r
|
|
182
|
+
this.base = off
|
|
183
|
+
this.off = off
|
|
184
|
+
this.limit = off + n
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
Read(p: Uint8Array): [number, $.GoError] {
|
|
188
|
+
if (this.off >= this.limit) {
|
|
189
|
+
return [0, EOF]
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
let max = this.limit - this.off
|
|
193
|
+
if (p.length > max) {
|
|
194
|
+
p = p.subarray(0, max)
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
const [n, err] = this.r.ReadAt(p, this.off)
|
|
198
|
+
this.off += n
|
|
199
|
+
return [n, err]
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
Seek(offset: number, whence: number): [number, $.GoError] {
|
|
203
|
+
let abs: number
|
|
204
|
+
switch (whence) {
|
|
205
|
+
case SeekStart:
|
|
206
|
+
abs = this.base + offset
|
|
207
|
+
break
|
|
208
|
+
case SeekCurrent:
|
|
209
|
+
abs = this.off + offset
|
|
210
|
+
break
|
|
211
|
+
case SeekEnd:
|
|
212
|
+
abs = this.limit + offset
|
|
213
|
+
break
|
|
214
|
+
default:
|
|
215
|
+
return [0, newError('io.SectionReader.Seek: invalid whence')]
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
if (abs < this.base) {
|
|
219
|
+
return [0, newError('io.SectionReader.Seek: negative position')]
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
this.off = abs
|
|
223
|
+
return [abs - this.base, null]
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
ReadAt(p: Uint8Array, off: number): [number, $.GoError] {
|
|
227
|
+
if (off < 0 || off >= this.limit - this.base) {
|
|
228
|
+
return [0, EOF]
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
off += this.base
|
|
232
|
+
if (off + p.length > this.limit) {
|
|
233
|
+
p = p.subarray(0, this.limit - off)
|
|
234
|
+
const [n, err] = this.r.ReadAt(p, off)
|
|
235
|
+
if (err === null) {
|
|
236
|
+
return [n, EOF]
|
|
237
|
+
}
|
|
238
|
+
return [n, err]
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
return this.r.ReadAt(p, off)
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
Size(): number {
|
|
245
|
+
return this.limit - this.base
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// NewSectionReader returns a SectionReader that reads from r starting at offset off and stops with EOF after n bytes
|
|
250
|
+
export function NewSectionReader(
|
|
251
|
+
r: ReaderAt,
|
|
252
|
+
off: number,
|
|
253
|
+
n: number,
|
|
254
|
+
): SectionReader {
|
|
255
|
+
return new SectionReader(r, off, n)
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
// OffsetWriter maps writes at offset base to offset base+off in the underlying writer
|
|
259
|
+
export class OffsetWriter implements Writer, WriterAt {
|
|
260
|
+
private w: WriterAt
|
|
261
|
+
private base: number
|
|
262
|
+
private off: number
|
|
263
|
+
|
|
264
|
+
constructor(w: WriterAt, off: number) {
|
|
265
|
+
this.w = w
|
|
266
|
+
this.base = off
|
|
267
|
+
this.off = 0
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
Write(p: Uint8Array): [number, $.GoError] {
|
|
271
|
+
const [n, err] = this.w.WriteAt(p, this.base + this.off)
|
|
272
|
+
this.off += n
|
|
273
|
+
return [n, err]
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
WriteAt(p: Uint8Array, off: number): [number, $.GoError] {
|
|
277
|
+
if (off < 0) {
|
|
278
|
+
return [0, newError('io.OffsetWriter.WriteAt: negative offset')]
|
|
279
|
+
}
|
|
280
|
+
return this.w.WriteAt(p, this.base + off)
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
Seek(offset: number, whence: number): [number, $.GoError] {
|
|
284
|
+
let abs: number
|
|
285
|
+
switch (whence) {
|
|
286
|
+
case SeekStart:
|
|
287
|
+
abs = offset
|
|
288
|
+
break
|
|
289
|
+
case SeekCurrent:
|
|
290
|
+
abs = this.off + offset
|
|
291
|
+
break
|
|
292
|
+
default:
|
|
293
|
+
return [0, newError('io.OffsetWriter.Seek: invalid whence')]
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
if (abs < 0) {
|
|
297
|
+
return [0, newError('io.OffsetWriter.Seek: negative position')]
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
this.off = abs
|
|
301
|
+
return [abs, null]
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
// NewOffsetWriter returns an OffsetWriter that writes to w starting at offset off
|
|
306
|
+
export function NewOffsetWriter(w: WriterAt, off: number): OffsetWriter {
|
|
307
|
+
return new OffsetWriter(w, off)
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
// Copy copies from src to dst until either EOF is reached on src or an error occurs
|
|
311
|
+
export function Copy(dst: Writer, src: Reader): [number, $.GoError] {
|
|
312
|
+
return CopyBuffer(dst, src, null)
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
// CopyBuffer is identical to Copy except that it stages through the provided buffer
|
|
316
|
+
export function CopyBuffer(
|
|
317
|
+
dst: Writer,
|
|
318
|
+
src: Reader,
|
|
319
|
+
buf: Uint8Array | null,
|
|
320
|
+
): [number, $.GoError] {
|
|
321
|
+
// If src implements WriterTo, use it
|
|
322
|
+
if ('WriteTo' in src && typeof (src as any).WriteTo === 'function') {
|
|
323
|
+
return (src as WriterTo).WriteTo(dst)
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
// If dst implements ReaderFrom, use it
|
|
327
|
+
if ('ReadFrom' in dst && typeof (dst as any).ReadFrom === 'function') {
|
|
328
|
+
return (dst as ReaderFrom).ReadFrom(src)
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
if (buf === null) {
|
|
332
|
+
buf = new Uint8Array(32 * 1024) // 32KB default buffer
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
let written = 0
|
|
336
|
+
while (true) {
|
|
337
|
+
const [nr, er] = src.Read(buf)
|
|
338
|
+
if (nr > 0) {
|
|
339
|
+
const [nw, ew] = dst.Write(buf.subarray(0, nr))
|
|
340
|
+
if (nw < 0 || nr < nw) {
|
|
341
|
+
if (ew === null) {
|
|
342
|
+
return [written, ErrShortWrite]
|
|
343
|
+
}
|
|
344
|
+
return [written, ew]
|
|
345
|
+
}
|
|
346
|
+
written += nw
|
|
347
|
+
if (ew !== null) {
|
|
348
|
+
return [written, ew]
|
|
349
|
+
}
|
|
350
|
+
if (nr !== nw) {
|
|
351
|
+
return [written, ErrShortWrite]
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
if (er !== null) {
|
|
355
|
+
if (er === EOF) {
|
|
356
|
+
break
|
|
357
|
+
}
|
|
358
|
+
return [written, er]
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
return [written, null]
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
// CopyN copies n bytes (or until an error) from src to dst
|
|
365
|
+
export function CopyN(
|
|
366
|
+
dst: Writer,
|
|
367
|
+
src: Reader,
|
|
368
|
+
n: number,
|
|
369
|
+
): [number, $.GoError] {
|
|
370
|
+
const [written, err] = Copy(dst, LimitReader(src, n))
|
|
371
|
+
if (written === n) {
|
|
372
|
+
return [written, null]
|
|
373
|
+
}
|
|
374
|
+
if (written < n && err === null) {
|
|
375
|
+
// src stopped early; must have been EOF
|
|
376
|
+
return [written, EOF]
|
|
377
|
+
}
|
|
378
|
+
return [written, err]
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
// ReadAtLeast reads from r into buf until it has read at least min bytes
|
|
382
|
+
export function ReadAtLeast(
|
|
383
|
+
r: Reader,
|
|
384
|
+
buf: Uint8Array,
|
|
385
|
+
min: number,
|
|
386
|
+
): [number, $.GoError] {
|
|
387
|
+
if (buf.length < min) {
|
|
388
|
+
return [0, ErrShortBuffer]
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
let n = 0
|
|
392
|
+
while (n < min) {
|
|
393
|
+
const [nn, err] = r.Read(buf.subarray(n))
|
|
394
|
+
n += nn
|
|
395
|
+
if (err !== null) {
|
|
396
|
+
if (err === EOF && n >= min) {
|
|
397
|
+
return [n, null]
|
|
398
|
+
}
|
|
399
|
+
if (err === EOF && n < min) {
|
|
400
|
+
return [n, ErrUnexpectedEOF]
|
|
401
|
+
}
|
|
402
|
+
return [n, err]
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
return [n, null]
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
// ReadFull reads exactly len(buf) bytes from r into buf
|
|
409
|
+
export function ReadFull(r: Reader, buf: Uint8Array): [number, $.GoError] {
|
|
410
|
+
return ReadAtLeast(r, buf, buf.length)
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
// ReadAll reads from r until an error or EOF and returns the data it read
|
|
414
|
+
export function ReadAll(r: Reader): [Uint8Array, $.GoError] {
|
|
415
|
+
const chunks: Uint8Array[] = []
|
|
416
|
+
let totalLength = 0
|
|
417
|
+
const buf = new Uint8Array(512)
|
|
418
|
+
|
|
419
|
+
while (true) {
|
|
420
|
+
const [n, err] = r.Read(buf)
|
|
421
|
+
if (n > 0) {
|
|
422
|
+
chunks.push(buf.subarray(0, n))
|
|
423
|
+
totalLength += n
|
|
424
|
+
}
|
|
425
|
+
if (err !== null) {
|
|
426
|
+
if (err === EOF) {
|
|
427
|
+
break
|
|
428
|
+
}
|
|
429
|
+
return [new Uint8Array(0), err]
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
// Combine all chunks
|
|
434
|
+
const result = new Uint8Array(totalLength)
|
|
435
|
+
let offset = 0
|
|
436
|
+
for (const chunk of chunks) {
|
|
437
|
+
result.set(chunk, offset)
|
|
438
|
+
offset += chunk.length
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
return [result, null]
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
// NopCloser returns a ReadCloser with a no-op Close method wrapping the provided Reader r
|
|
445
|
+
export function NopCloser(r: Reader): ReadCloser {
|
|
446
|
+
return {
|
|
447
|
+
Read: r.Read.bind(r),
|
|
448
|
+
Close: () => null,
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
// MultiReader returns a Reader that's the logical concatenation of the provided input readers
|
|
453
|
+
export function MultiReader(...readers: Reader[]): Reader {
|
|
454
|
+
return new multiReader(readers.slice())
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
class multiReader implements Reader {
|
|
458
|
+
private readers: Reader[]
|
|
459
|
+
|
|
460
|
+
constructor(readers: Reader[]) {
|
|
461
|
+
this.readers = readers
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
Read(p: Uint8Array): [number, $.GoError] {
|
|
465
|
+
while (this.readers.length > 0) {
|
|
466
|
+
if (this.readers.length === 1) {
|
|
467
|
+
// Optimization for single reader
|
|
468
|
+
const r = this.readers[0]
|
|
469
|
+
const [n, err] = r.Read(p)
|
|
470
|
+
if (err === EOF) {
|
|
471
|
+
this.readers = []
|
|
472
|
+
}
|
|
473
|
+
return [n, err]
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
const [n, err] = this.readers[0].Read(p)
|
|
477
|
+
if (err === EOF) {
|
|
478
|
+
this.readers.shift() // Remove first reader
|
|
479
|
+
continue
|
|
480
|
+
}
|
|
481
|
+
if (n > 0 || err !== EOF) {
|
|
482
|
+
if (err === EOF && this.readers.length > 1) {
|
|
483
|
+
// Don't return EOF if there are more readers
|
|
484
|
+
return [n, null]
|
|
485
|
+
}
|
|
486
|
+
return [n, err]
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
return [0, EOF]
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
// MultiWriter creates a writer that duplicates its writes to all the provided writers
|
|
494
|
+
export function MultiWriter(...writers: Writer[]): Writer {
|
|
495
|
+
return new multiWriter(writers.slice())
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
class multiWriter implements Writer {
|
|
499
|
+
private writers: Writer[]
|
|
500
|
+
|
|
501
|
+
constructor(writers: Writer[]) {
|
|
502
|
+
this.writers = writers
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
Write(p: Uint8Array): [number, $.GoError] {
|
|
506
|
+
for (const w of this.writers) {
|
|
507
|
+
const [n, err] = w.Write(p)
|
|
508
|
+
if (err !== null) {
|
|
509
|
+
return [n, err]
|
|
510
|
+
}
|
|
511
|
+
if (n !== p.length) {
|
|
512
|
+
return [n, ErrShortWrite]
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
return [p.length, null]
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
// TeeReader returns a Reader that writes to w what it reads from r
|
|
520
|
+
export function TeeReader(r: Reader, w: Writer): Reader {
|
|
521
|
+
return new teeReader(r, w)
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
class teeReader implements Reader {
|
|
525
|
+
private r: Reader
|
|
526
|
+
private w: Writer
|
|
527
|
+
|
|
528
|
+
constructor(r: Reader, w: Writer) {
|
|
529
|
+
this.r = r
|
|
530
|
+
this.w = w
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
Read(p: Uint8Array): [number, $.GoError] {
|
|
534
|
+
const [n, err] = this.r.Read(p)
|
|
535
|
+
if (n > 0) {
|
|
536
|
+
const [nw, ew] = this.w.Write(p.subarray(0, n))
|
|
537
|
+
if (ew !== null) {
|
|
538
|
+
return [n, ew]
|
|
539
|
+
}
|
|
540
|
+
if (nw !== n) {
|
|
541
|
+
return [n, ErrShortWrite]
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
return [n, err]
|
|
545
|
+
}
|
|
546
|
+
}
|