goscript 0.0.26 → 0.0.29

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 (228) hide show
  1. package/README.md +4 -4
  2. package/cmd/goscript/cmd_compile.go +0 -3
  3. package/cmd/goscript/deps.go +11 -0
  4. package/compiler/analysis.go +298 -55
  5. package/compiler/assignment.go +2 -2
  6. package/compiler/builtin_test.go +1 -1
  7. package/compiler/compiler.go +200 -68
  8. package/compiler/compiler_test.go +17 -24
  9. package/compiler/composite-lit.go +32 -8
  10. package/compiler/decl.go +6 -6
  11. package/compiler/expr-call.go +170 -15
  12. package/compiler/expr-selector.go +100 -0
  13. package/compiler/expr.go +1 -1
  14. package/compiler/protobuf.go +557 -0
  15. package/compiler/spec-struct.go +4 -0
  16. package/compiler/spec-value.go +89 -10
  17. package/compiler/spec.go +254 -1
  18. package/compiler/stmt-assign.go +35 -0
  19. package/compiler/type-assert.go +87 -0
  20. package/compiler/type.go +4 -1
  21. package/dist/gs/builtin/builtin.d.ts +20 -1
  22. package/dist/gs/builtin/builtin.js +95 -4
  23. package/dist/gs/builtin/builtin.js.map +1 -1
  24. package/dist/gs/builtin/slice.d.ts +1 -1
  25. package/dist/gs/builtin/slice.js +21 -2
  26. package/dist/gs/builtin/slice.js.map +1 -1
  27. package/dist/gs/errors/errors.d.ts +5 -6
  28. package/dist/gs/errors/errors.js.map +1 -1
  29. package/dist/gs/internal/oserror/errors.d.ts +6 -0
  30. package/dist/gs/internal/oserror/errors.js +7 -0
  31. package/dist/gs/internal/oserror/errors.js.map +1 -0
  32. package/dist/gs/internal/oserror/index.d.ts +1 -0
  33. package/dist/gs/internal/oserror/index.js +2 -0
  34. package/dist/gs/internal/oserror/index.js.map +1 -0
  35. package/dist/gs/io/fs/format.d.ts +3 -0
  36. package/dist/gs/io/fs/format.js +56 -0
  37. package/dist/gs/io/fs/format.js.map +1 -0
  38. package/dist/gs/io/fs/fs.d.ts +79 -0
  39. package/dist/gs/io/fs/fs.js +200 -0
  40. package/dist/gs/io/fs/fs.js.map +1 -0
  41. package/dist/gs/io/fs/glob.d.ts +10 -0
  42. package/dist/gs/io/fs/glob.js +141 -0
  43. package/dist/gs/io/fs/glob.js.map +1 -0
  44. package/dist/gs/io/fs/index.d.ts +8 -0
  45. package/dist/gs/io/fs/index.js +9 -0
  46. package/dist/gs/io/fs/index.js.map +1 -0
  47. package/dist/gs/io/fs/readdir.d.ts +7 -0
  48. package/dist/gs/io/fs/readdir.js +152 -0
  49. package/dist/gs/io/fs/readdir.js.map +1 -0
  50. package/dist/gs/io/fs/readfile.d.ts +6 -0
  51. package/dist/gs/io/fs/readfile.js +118 -0
  52. package/dist/gs/io/fs/readfile.js.map +1 -0
  53. package/dist/gs/io/fs/stat.d.ts +6 -0
  54. package/dist/gs/io/fs/stat.js +87 -0
  55. package/dist/gs/io/fs/stat.js.map +1 -0
  56. package/dist/gs/io/fs/sub.d.ts +6 -0
  57. package/dist/gs/io/fs/sub.js +172 -0
  58. package/dist/gs/io/fs/sub.js.map +1 -0
  59. package/dist/gs/io/fs/walk.d.ts +7 -0
  60. package/dist/gs/io/fs/walk.js +76 -0
  61. package/dist/gs/io/fs/walk.js.map +1 -0
  62. package/dist/gs/io/index.d.ts +1 -0
  63. package/dist/gs/io/index.js +2 -0
  64. package/dist/gs/io/index.js.map +1 -0
  65. package/dist/gs/io/io.d.ts +107 -0
  66. package/dist/gs/io/io.js +385 -0
  67. package/dist/gs/io/io.js.map +1 -0
  68. package/dist/gs/path/index.d.ts +2 -0
  69. package/dist/gs/path/index.js +3 -0
  70. package/dist/gs/path/index.js.map +1 -0
  71. package/dist/gs/path/match.d.ts +6 -0
  72. package/dist/gs/path/match.js +281 -0
  73. package/dist/gs/path/match.js.map +1 -0
  74. package/dist/gs/path/path.d.ts +7 -0
  75. package/dist/gs/path/path.js +256 -0
  76. package/dist/gs/path/path.js.map +1 -0
  77. package/dist/gs/strings/builder.d.ts +18 -0
  78. package/dist/gs/strings/builder.js +205 -0
  79. package/dist/gs/strings/builder.js.map +1 -0
  80. package/dist/gs/strings/clone.d.ts +1 -0
  81. package/dist/gs/strings/clone.js +16 -0
  82. package/dist/gs/strings/clone.js.map +1 -0
  83. package/dist/gs/strings/compare.d.ts +1 -0
  84. package/dist/gs/strings/compare.js +14 -0
  85. package/dist/gs/strings/compare.js.map +1 -0
  86. package/dist/gs/strings/index.d.ts +2 -0
  87. package/dist/gs/strings/index.js +3 -0
  88. package/dist/gs/strings/index.js.map +1 -0
  89. package/dist/gs/strings/iter.d.ts +8 -0
  90. package/dist/gs/strings/iter.js +160 -0
  91. package/dist/gs/strings/iter.js.map +1 -0
  92. package/dist/gs/strings/reader.d.ts +34 -0
  93. package/dist/gs/strings/reader.js +418 -0
  94. package/dist/gs/strings/reader.js.map +1 -0
  95. package/dist/gs/strings/replace.d.ts +106 -0
  96. package/dist/gs/strings/replace.js +1136 -0
  97. package/dist/gs/strings/replace.js.map +1 -0
  98. package/dist/gs/strings/search.d.ts +24 -0
  99. package/dist/gs/strings/search.js +169 -0
  100. package/dist/gs/strings/search.js.map +1 -0
  101. package/dist/gs/strings/strings.d.ts +47 -0
  102. package/dist/gs/strings/strings.js +418 -0
  103. package/dist/gs/strings/strings.js.map +1 -0
  104. package/dist/gs/stringslite/index.d.ts +1 -0
  105. package/dist/gs/stringslite/index.js +2 -0
  106. package/dist/gs/stringslite/index.js.map +1 -0
  107. package/dist/gs/stringslite/strings.d.ts +11 -0
  108. package/dist/gs/stringslite/strings.js +67 -0
  109. package/dist/gs/stringslite/strings.js.map +1 -0
  110. package/dist/gs/sync/index.d.ts +1 -0
  111. package/dist/gs/sync/index.js +2 -0
  112. package/dist/gs/sync/index.js.map +1 -0
  113. package/dist/gs/sync/sync.d.ts +79 -0
  114. package/dist/gs/sync/sync.js +392 -0
  115. package/dist/gs/sync/sync.js.map +1 -0
  116. package/dist/gs/time/time.d.ts +11 -2
  117. package/dist/gs/time/time.js +337 -12
  118. package/dist/gs/time/time.js.map +1 -1
  119. package/dist/gs/unicode/index.d.ts +1 -0
  120. package/dist/gs/unicode/index.js +2 -0
  121. package/dist/gs/unicode/index.js.map +1 -0
  122. package/dist/gs/unicode/unicode.d.ts +105 -0
  123. package/dist/gs/unicode/unicode.js +332 -0
  124. package/dist/gs/unicode/unicode.js.map +1 -0
  125. package/dist/gs/unicode/utf8/index.d.ts +1 -0
  126. package/dist/gs/unicode/utf8/index.js +3 -0
  127. package/dist/gs/unicode/utf8/index.js.map +1 -0
  128. package/dist/gs/unicode/utf8/utf8.d.ts +20 -0
  129. package/dist/gs/unicode/utf8/utf8.js +196 -0
  130. package/dist/gs/unicode/utf8/utf8.js.map +1 -0
  131. package/dist/gs/unsafe/index.d.ts +1 -0
  132. package/dist/gs/unsafe/index.js +2 -0
  133. package/dist/gs/unsafe/index.js.map +1 -0
  134. package/dist/gs/unsafe/unsafe.d.ts +11 -0
  135. package/dist/gs/unsafe/unsafe.js +44 -0
  136. package/dist/gs/unsafe/unsafe.js.map +1 -0
  137. package/go.mod +2 -1
  138. package/go.sum +6 -2
  139. package/gs/README.md +6 -0
  140. package/gs/builtin/builtin.ts +171 -0
  141. package/gs/builtin/channel.ts +683 -0
  142. package/gs/builtin/defer.ts +58 -0
  143. package/gs/builtin/index.ts +1 -0
  144. package/gs/builtin/io.ts +22 -0
  145. package/gs/builtin/map.ts +50 -0
  146. package/gs/builtin/slice.ts +1030 -0
  147. package/gs/builtin/type.ts +1106 -0
  148. package/gs/builtin/varRef.ts +25 -0
  149. package/gs/cmp/godoc.txt +8 -0
  150. package/gs/cmp/index.ts +29 -0
  151. package/gs/context/context.ts +401 -0
  152. package/gs/context/godoc.txt +69 -0
  153. package/gs/context/index.ts +1 -0
  154. package/gs/errors/errors.ts +223 -0
  155. package/gs/errors/godoc.txt +63 -0
  156. package/gs/errors/index.ts +1 -0
  157. package/gs/internal/goarch/godoc.txt +39 -0
  158. package/gs/internal/goarch/index.ts +18 -0
  159. package/gs/internal/oserror/errors.ts +14 -0
  160. package/gs/internal/oserror/index.ts +1 -0
  161. package/gs/io/fs/format.ts +65 -0
  162. package/gs/io/fs/fs.ts +359 -0
  163. package/gs/io/fs/glob.ts +167 -0
  164. package/gs/io/fs/godoc.txt +35 -0
  165. package/gs/io/fs/index.ts +8 -0
  166. package/gs/io/fs/readdir.ts +126 -0
  167. package/gs/io/fs/readfile.ts +77 -0
  168. package/gs/io/fs/stat.ts +38 -0
  169. package/gs/io/fs/sub.ts +208 -0
  170. package/gs/io/fs/walk.ts +89 -0
  171. package/gs/io/godoc.txt +61 -0
  172. package/gs/io/index.ts +1 -0
  173. package/gs/io/io.go +75 -0
  174. package/gs/io/io.ts +546 -0
  175. package/gs/iter/godoc.txt +203 -0
  176. package/gs/iter/index.ts +1 -0
  177. package/gs/iter/iter.ts +117 -0
  178. package/gs/math/bits/index.ts +356 -0
  179. package/gs/math/godoc.txt +76 -0
  180. package/gs/path/index.ts +2 -0
  181. package/gs/path/match.ts +307 -0
  182. package/gs/path/path.ts +301 -0
  183. package/gs/runtime/godoc.txt +331 -0
  184. package/gs/runtime/index.ts +1 -0
  185. package/gs/runtime/runtime.ts +178 -0
  186. package/gs/slices/godoc.txt +44 -0
  187. package/gs/slices/index.ts +1 -0
  188. package/gs/slices/slices.ts +22 -0
  189. package/gs/strings/builder.test.ts +121 -0
  190. package/gs/strings/builder.ts +223 -0
  191. package/gs/strings/clone.test.ts +43 -0
  192. package/gs/strings/clone.ts +17 -0
  193. package/gs/strings/compare.test.ts +84 -0
  194. package/gs/strings/compare.ts +13 -0
  195. package/gs/strings/godoc.txt +66 -0
  196. package/gs/strings/index.ts +2 -0
  197. package/gs/strings/iter.test.ts +343 -0
  198. package/gs/strings/iter.ts +171 -0
  199. package/gs/strings/reader.test.ts +242 -0
  200. package/gs/strings/reader.ts +451 -0
  201. package/gs/strings/replace.test.ts +181 -0
  202. package/gs/strings/replace.ts +1310 -0
  203. package/gs/strings/search.test.ts +214 -0
  204. package/gs/strings/search.ts +213 -0
  205. package/gs/strings/strings.test.ts +477 -0
  206. package/gs/strings/strings.ts +510 -0
  207. package/gs/stringslite/godoc.txt +17 -0
  208. package/gs/stringslite/index.ts +1 -0
  209. package/gs/stringslite/strings.ts +82 -0
  210. package/gs/sync/godoc.txt +21 -0
  211. package/gs/sync/index.ts +1 -0
  212. package/gs/sync/sync.go +64 -0
  213. package/gs/sync/sync.ts +449 -0
  214. package/gs/time/godoc.txt +116 -0
  215. package/gs/time/index.ts +1 -0
  216. package/gs/time/time.ts +585 -0
  217. package/gs/unicode/godoc.txt +52 -0
  218. package/gs/unicode/index.ts +1 -0
  219. package/gs/unicode/unicode.go +38 -0
  220. package/gs/unicode/unicode.ts +418 -0
  221. package/gs/unicode/utf8/godoc.txt +22 -0
  222. package/gs/unicode/utf8/index.ts +2 -0
  223. package/gs/unicode/utf8/utf8.ts +227 -0
  224. package/gs/unsafe/godoc.txt +19 -0
  225. package/gs/unsafe/index.ts +1 -0
  226. package/gs/unsafe/unsafe.test.ts +68 -0
  227. package/gs/unsafe/unsafe.ts +77 -0
  228. package/package.json +4 -3
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
+ }