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.
Files changed (190) 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 +259 -55
  5. package/compiler/assignment.go +2 -2
  6. package/compiler/builtin_test.go +1 -1
  7. package/compiler/compiler.go +201 -49
  8. package/compiler/compiler_test.go +53 -0
  9. package/compiler/composite-lit.go +32 -8
  10. package/compiler/decl.go +6 -6
  11. package/compiler/expr-call.go +83 -0
  12. package/compiler/expr.go +1 -1
  13. package/compiler/protobuf.go +557 -0
  14. package/compiler/spec-struct.go +4 -0
  15. package/compiler/spec-value.go +11 -3
  16. package/compiler/spec.go +18 -1
  17. package/compiler/stmt-assign.go +35 -0
  18. package/compiler/type-assert.go +87 -0
  19. package/compiler/type.go +5 -2
  20. package/dist/gs/builtin/builtin.d.ts +19 -1
  21. package/dist/gs/builtin/builtin.js +85 -5
  22. package/dist/gs/builtin/builtin.js.map +1 -1
  23. package/dist/gs/builtin/channel.js.map +1 -1
  24. package/dist/gs/builtin/slice.d.ts +1 -1
  25. package/dist/gs/builtin/slice.js +59 -26
  26. package/dist/gs/builtin/slice.js.map +1 -1
  27. package/dist/gs/cmp/index.js.map +1 -1
  28. package/dist/gs/context/context.d.ts +1 -1
  29. package/dist/gs/context/context.js +20 -11
  30. package/dist/gs/context/context.js.map +1 -1
  31. package/dist/gs/errors/errors.d.ts +7 -0
  32. package/dist/gs/errors/errors.js +190 -0
  33. package/dist/gs/errors/errors.js.map +1 -0
  34. package/dist/gs/errors/index.d.ts +1 -0
  35. package/dist/gs/errors/index.js +2 -0
  36. package/dist/gs/errors/index.js.map +1 -0
  37. package/dist/gs/internal/goarch/index.js +1 -1
  38. package/dist/gs/internal/goarch/index.js.map +1 -1
  39. package/dist/gs/io/index.d.ts +1 -0
  40. package/dist/gs/io/index.js +2 -0
  41. package/dist/gs/io/index.js.map +1 -0
  42. package/dist/gs/io/io.d.ts +107 -0
  43. package/dist/gs/io/io.js +385 -0
  44. package/dist/gs/io/io.js.map +1 -0
  45. package/dist/gs/iter/iter.js.map +1 -1
  46. package/dist/gs/math/bits/index.js +34 -32
  47. package/dist/gs/math/bits/index.js.map +1 -1
  48. package/dist/gs/runtime/runtime.d.ts +1 -0
  49. package/dist/gs/runtime/runtime.js +15 -18
  50. package/dist/gs/runtime/runtime.js.map +1 -1
  51. package/dist/gs/slices/slices.d.ts +1 -1
  52. package/dist/gs/slices/slices.js +1 -1
  53. package/dist/gs/slices/slices.js.map +1 -1
  54. package/dist/gs/strings/builder.d.ts +18 -0
  55. package/dist/gs/strings/builder.js +205 -0
  56. package/dist/gs/strings/builder.js.map +1 -0
  57. package/dist/gs/strings/clone.d.ts +1 -0
  58. package/dist/gs/strings/clone.js +16 -0
  59. package/dist/gs/strings/clone.js.map +1 -0
  60. package/dist/gs/strings/compare.d.ts +1 -0
  61. package/dist/gs/strings/compare.js +14 -0
  62. package/dist/gs/strings/compare.js.map +1 -0
  63. package/dist/gs/strings/index.d.ts +2 -0
  64. package/dist/gs/strings/index.js +3 -0
  65. package/dist/gs/strings/index.js.map +1 -0
  66. package/dist/gs/strings/iter.d.ts +8 -0
  67. package/dist/gs/strings/iter.js +160 -0
  68. package/dist/gs/strings/iter.js.map +1 -0
  69. package/dist/gs/strings/reader.d.ts +34 -0
  70. package/dist/gs/strings/reader.js +418 -0
  71. package/dist/gs/strings/reader.js.map +1 -0
  72. package/dist/gs/strings/replace.d.ts +106 -0
  73. package/dist/gs/strings/replace.js +1136 -0
  74. package/dist/gs/strings/replace.js.map +1 -0
  75. package/dist/gs/strings/search.d.ts +24 -0
  76. package/dist/gs/strings/search.js +169 -0
  77. package/dist/gs/strings/search.js.map +1 -0
  78. package/dist/gs/strings/strings.d.ts +47 -0
  79. package/dist/gs/strings/strings.js +418 -0
  80. package/dist/gs/strings/strings.js.map +1 -0
  81. package/dist/gs/stringslite/index.d.ts +1 -0
  82. package/dist/gs/stringslite/index.js +2 -0
  83. package/dist/gs/stringslite/index.js.map +1 -0
  84. package/dist/gs/stringslite/strings.d.ts +11 -0
  85. package/dist/gs/stringslite/strings.js +67 -0
  86. package/dist/gs/stringslite/strings.js.map +1 -0
  87. package/dist/gs/sync/index.d.ts +1 -0
  88. package/dist/gs/sync/index.js +2 -0
  89. package/dist/gs/sync/index.js.map +1 -0
  90. package/dist/gs/sync/sync.d.ts +79 -0
  91. package/dist/gs/sync/sync.js +392 -0
  92. package/dist/gs/sync/sync.js.map +1 -0
  93. package/dist/gs/time/time.js +7 -7
  94. package/dist/gs/time/time.js.map +1 -1
  95. package/dist/gs/unicode/index.d.ts +1 -0
  96. package/dist/gs/unicode/index.js +2 -0
  97. package/dist/gs/unicode/index.js.map +1 -0
  98. package/dist/gs/unicode/unicode.d.ts +105 -0
  99. package/dist/gs/unicode/unicode.js +332 -0
  100. package/dist/gs/unicode/unicode.js.map +1 -0
  101. package/dist/gs/unicode/utf8/index.d.ts +1 -0
  102. package/dist/gs/unicode/utf8/index.js +3 -0
  103. package/dist/gs/unicode/utf8/index.js.map +1 -0
  104. package/dist/gs/unicode/utf8/utf8.d.ts +20 -0
  105. package/dist/gs/unicode/utf8/utf8.js +196 -0
  106. package/dist/gs/unicode/utf8/utf8.js.map +1 -0
  107. package/dist/gs/unsafe/index.d.ts +1 -0
  108. package/dist/gs/unsafe/index.js +2 -0
  109. package/dist/gs/unsafe/index.js.map +1 -0
  110. package/dist/gs/unsafe/unsafe.d.ts +11 -0
  111. package/dist/gs/unsafe/unsafe.js +44 -0
  112. package/dist/gs/unsafe/unsafe.js.map +1 -0
  113. package/go.mod +2 -1
  114. package/go.sum +6 -2
  115. package/gs/README.md +6 -0
  116. package/gs/builtin/builtin.ts +158 -0
  117. package/gs/builtin/channel.ts +683 -0
  118. package/gs/builtin/defer.ts +58 -0
  119. package/gs/builtin/index.ts +1 -0
  120. package/gs/builtin/io.ts +22 -0
  121. package/gs/builtin/map.ts +50 -0
  122. package/gs/builtin/slice.ts +1030 -0
  123. package/gs/builtin/type.ts +1106 -0
  124. package/gs/builtin/varRef.ts +25 -0
  125. package/gs/cmp/godoc.txt +8 -0
  126. package/gs/cmp/index.ts +29 -0
  127. package/gs/context/context.ts +401 -0
  128. package/gs/context/godoc.txt +69 -0
  129. package/gs/context/index.ts +1 -0
  130. package/gs/errors/errors.ts +223 -0
  131. package/gs/errors/godoc.txt +63 -0
  132. package/gs/errors/index.ts +1 -0
  133. package/gs/internal/goarch/godoc.txt +39 -0
  134. package/gs/internal/goarch/index.ts +18 -0
  135. package/gs/io/godoc.txt +61 -0
  136. package/gs/io/index.ts +1 -0
  137. package/gs/io/io.go +75 -0
  138. package/gs/io/io.ts +546 -0
  139. package/gs/iter/godoc.txt +203 -0
  140. package/gs/iter/index.ts +1 -0
  141. package/gs/iter/iter.ts +117 -0
  142. package/gs/math/bits/index.ts +356 -0
  143. package/gs/math/godoc.txt +76 -0
  144. package/gs/runtime/godoc.txt +331 -0
  145. package/gs/runtime/index.ts +1 -0
  146. package/gs/runtime/runtime.ts +178 -0
  147. package/gs/slices/godoc.txt +44 -0
  148. package/gs/slices/index.ts +1 -0
  149. package/gs/slices/slices.ts +22 -0
  150. package/gs/strings/builder.test.ts +121 -0
  151. package/gs/strings/builder.ts +223 -0
  152. package/gs/strings/clone.test.ts +43 -0
  153. package/gs/strings/clone.ts +17 -0
  154. package/gs/strings/compare.test.ts +84 -0
  155. package/gs/strings/compare.ts +13 -0
  156. package/gs/strings/godoc.txt +66 -0
  157. package/gs/strings/index.ts +2 -0
  158. package/gs/strings/iter.test.ts +343 -0
  159. package/gs/strings/iter.ts +171 -0
  160. package/gs/strings/reader.test.ts +243 -0
  161. package/gs/strings/reader.ts +451 -0
  162. package/gs/strings/replace.test.ts +181 -0
  163. package/gs/strings/replace.ts +1310 -0
  164. package/gs/strings/search.test.ts +214 -0
  165. package/gs/strings/search.ts +213 -0
  166. package/gs/strings/strings.test.ts +477 -0
  167. package/gs/strings/strings.ts +510 -0
  168. package/gs/stringslite/godoc.txt +17 -0
  169. package/gs/stringslite/index.ts +1 -0
  170. package/gs/stringslite/strings.ts +82 -0
  171. package/gs/sync/godoc.txt +21 -0
  172. package/gs/sync/index.ts +1 -0
  173. package/gs/sync/sync.go +64 -0
  174. package/gs/sync/sync.ts +449 -0
  175. package/gs/time/godoc.md +116 -0
  176. package/gs/time/godoc.txt +116 -0
  177. package/gs/time/index.ts +1 -0
  178. package/gs/time/time.ts +272 -0
  179. package/gs/unicode/godoc.txt +52 -0
  180. package/gs/unicode/index.ts +1 -0
  181. package/gs/unicode/unicode.go +38 -0
  182. package/gs/unicode/unicode.ts +418 -0
  183. package/gs/unicode/utf8/godoc.txt +22 -0
  184. package/gs/unicode/utf8/index.ts +2 -0
  185. package/gs/unicode/utf8/utf8.ts +227 -0
  186. package/gs/unsafe/godoc.txt +19 -0
  187. package/gs/unsafe/index.ts +1 -0
  188. package/gs/unsafe/unsafe.test.ts +68 -0
  189. package/gs/unsafe/unsafe.ts +77 -0
  190. package/package.json +6 -4
@@ -0,0 +1,243 @@
1
+ import { describe, it, expect } from 'vitest'
2
+ import * as $ from '@goscript/builtin/builtin.js'
3
+ import { Reader, NewReader } from './reader.js'
4
+ import * as io from '@goscript/io/index.js'
5
+
6
+ describe('strings/Reader', () => {
7
+ describe('NewReader', () => {
8
+ it('should create a new reader', () => {
9
+ const r = NewReader('hello world')
10
+ expect(r).not.toBeNull()
11
+ if (r) {
12
+ expect(r.Size()).toBe(11)
13
+ expect(r.Len()).toBe(11)
14
+ }
15
+ })
16
+ })
17
+
18
+ describe('Reader', () => {
19
+ it('should read bytes', () => {
20
+ const r = new Reader({ s: 'hello' })
21
+ const buf = new Uint8Array(3)
22
+
23
+ const [n, err] = r.Read(buf)
24
+ expect(n).toBe(3)
25
+ expect(err).toBeNull()
26
+ expect(new TextDecoder().decode(buf)).toBe('hel')
27
+ expect(r.Len()).toBe(2)
28
+ })
29
+
30
+ it('should read at specific offset', () => {
31
+ const r = new Reader({ s: 'hello world' })
32
+ const buf = new Uint8Array(5)
33
+
34
+ const [n, err] = r.ReadAt(buf, 6)
35
+ expect(n).toBe(5)
36
+ expect(err).toBeNull()
37
+ expect(new TextDecoder().decode(buf)).toBe('world')
38
+ })
39
+
40
+ it('should read at offset with EOF', () => {
41
+ const r = new Reader({ s: 'hello' })
42
+ const buf = new Uint8Array(10)
43
+
44
+ const [n, err] = r.ReadAt(buf, 2)
45
+ expect(n).toBe(3)
46
+ expect(err).toBe(io.EOF)
47
+ expect(new TextDecoder().decode(buf.subarray(0, n))).toBe('llo')
48
+ })
49
+
50
+ it('should handle negative offset in ReadAt', () => {
51
+ const r = new Reader({ s: 'hello' })
52
+ const buf = new Uint8Array(5)
53
+
54
+ const [n, err] = r.ReadAt(buf, -1)
55
+ expect(n).toBe(0)
56
+ expect(err).not.toBeNull()
57
+ })
58
+
59
+ it('should read byte', () => {
60
+ const r = new Reader({ s: 'hello' })
61
+
62
+ const [b, err] = r.ReadByte()
63
+ expect(b).toBe(104) // 'h'
64
+ expect(err).toBeNull()
65
+ expect(r.Len()).toBe(4)
66
+ })
67
+
68
+ it('should unread byte', () => {
69
+ const r = new Reader({ s: 'hello' })
70
+ r.ReadByte()
71
+
72
+ const err = r.UnreadByte()
73
+ expect(err).toBeNull()
74
+ expect(r.Len()).toBe(5)
75
+ })
76
+
77
+ it('should handle unread byte at beginning', () => {
78
+ const r = new Reader({ s: 'hello' })
79
+
80
+ const err = r.UnreadByte()
81
+ expect(err).not.toBeNull()
82
+ })
83
+
84
+ it('should read rune', () => {
85
+ const r = new Reader({ s: 'hello' })
86
+
87
+ const [rune, size, err] = r.ReadRune()
88
+ expect(rune).toBe(104) // 'h'
89
+ expect(size).toBe(1)
90
+ expect(err).toBeNull()
91
+ expect(r.Len()).toBe(4)
92
+ })
93
+
94
+ it('should read unicode rune', () => {
95
+ const r = new Reader({ s: '世界' })
96
+
97
+ const [rune, size, err] = r.ReadRune()
98
+ expect(rune).toBe(0x4e16) // '世'
99
+ expect(size).toBeGreaterThan(1)
100
+ expect(err).toBeNull()
101
+ })
102
+
103
+ it('should unread rune', () => {
104
+ const r = new Reader({ s: 'hello' })
105
+ r.ReadRune()
106
+
107
+ const err = r.UnreadRune()
108
+ expect(err).toBeNull()
109
+ expect(r.Len()).toBe(5)
110
+ })
111
+
112
+ it('should handle unread rune at beginning', () => {
113
+ const r = new Reader({ s: 'hello' })
114
+
115
+ const err = r.UnreadRune()
116
+ expect(err).not.toBeNull()
117
+ })
118
+
119
+ it('should handle unread rune without previous ReadRune', () => {
120
+ const r = new Reader({ s: 'hello' })
121
+ r.ReadByte()
122
+
123
+ const err = r.UnreadRune()
124
+ expect(err).not.toBeNull()
125
+ })
126
+
127
+ it('should seek from start', () => {
128
+ const r = new Reader({ s: 'hello world' })
129
+
130
+ const [pos, err] = r.Seek(6, io.SeekStart)
131
+ expect(pos).toBe(6)
132
+ expect(err).toBeNull()
133
+ expect(r.Len()).toBe(5)
134
+ })
135
+
136
+ it('should seek from current', () => {
137
+ const r = new Reader({ s: 'hello world' })
138
+ r.ReadByte() // advance to position 1
139
+
140
+ const [pos, err] = r.Seek(2, io.SeekCurrent)
141
+ expect(pos).toBe(3)
142
+ expect(err).toBeNull()
143
+ })
144
+
145
+ it('should seek from end', () => {
146
+ const r = new Reader({ s: 'hello world' })
147
+
148
+ const [pos, err] = r.Seek(-5, io.SeekEnd)
149
+ expect(pos).toBe(6)
150
+ expect(err).toBeNull()
151
+ })
152
+
153
+ it('should handle invalid whence in seek', () => {
154
+ const r = new Reader({ s: 'hello' })
155
+
156
+ const [pos, err] = r.Seek(0, 999)
157
+ expect(pos).toBe(0)
158
+ expect(err).not.toBeNull()
159
+ })
160
+
161
+ it('should handle negative position in seek', () => {
162
+ const r = new Reader({ s: 'hello' })
163
+
164
+ const [pos, err] = r.Seek(-10, io.SeekStart)
165
+ expect(pos).toBe(0)
166
+ expect(err).not.toBeNull()
167
+ })
168
+
169
+ it('should write to writer', () => {
170
+ const r = new Reader({ s: 'hello world' })
171
+ r.ReadByte() // advance position
172
+
173
+ const written: Uint8Array[] = []
174
+ const writer: io.Writer = {
175
+ Write: (p: Uint8Array) => {
176
+ written.push(p.slice())
177
+ return [p.length, null]
178
+ },
179
+ }
180
+
181
+ const [n, err] = r.WriteTo(writer)
182
+ expect(n).toBe(10) // remaining bytes
183
+ expect(err).toBeNull()
184
+ expect(r.Len()).toBe(0)
185
+ })
186
+
187
+ it('should reset reader', () => {
188
+ const r = new Reader({ s: 'hello' })
189
+ r.ReadByte()
190
+ expect(r.Len()).toBe(4)
191
+
192
+ r.Reset('world')
193
+ expect(r.Size()).toBe(5)
194
+ expect(r.Len()).toBe(5)
195
+ expect(r.s).toBe('world')
196
+ })
197
+
198
+ it('should handle EOF on read', () => {
199
+ const r = new Reader({ s: 'hi' })
200
+ const buf = new Uint8Array(10)
201
+
202
+ const [n, err] = r.Read(buf)
203
+ expect(n).toBe(2)
204
+ expect(err).toBeNull()
205
+
206
+ const [n2, err2] = r.Read(buf)
207
+ expect(n2).toBe(0)
208
+ expect(err2).toBe(io.EOF)
209
+ })
210
+
211
+ it('should handle EOF on ReadByte', () => {
212
+ const r = new Reader({ s: 'a' })
213
+ r.ReadByte()
214
+
215
+ const [b, err] = r.ReadByte()
216
+ expect(b).toBe(0)
217
+ expect(err).toBe(io.EOF)
218
+ })
219
+
220
+ it('should handle EOF on ReadRune', () => {
221
+ const r = new Reader({ s: 'a' })
222
+ r.ReadRune()
223
+
224
+ const [rune, size, err] = r.ReadRune()
225
+ expect(rune).toBe(0)
226
+ expect(size).toBe(0)
227
+ expect(err).toBe(io.EOF)
228
+ })
229
+
230
+ it('should clone reader', () => {
231
+ const r = new Reader({ s: 'hello', i: 2, prevRune: 1 })
232
+ const cloned = r.clone()
233
+
234
+ expect(cloned.s).toBe('hello')
235
+ expect(cloned.i).toBe(2)
236
+ expect(cloned.prevRune).toBe(1)
237
+
238
+ // Modify original
239
+ r.i = 3
240
+ expect(cloned.i).toBe(2) // Should not change
241
+ })
242
+ })
243
+ })
@@ -0,0 +1,451 @@
1
+ import * as $ from '@goscript/builtin/builtin.js'
2
+
3
+ import * as errors from '@goscript/errors/index.js'
4
+
5
+ import * as io from '@goscript/io/index.js'
6
+
7
+ import * as utf8 from '@goscript/unicode/utf8/index.js'
8
+
9
+ export class Reader {
10
+ public get s(): string {
11
+ return this._fields.s.value
12
+ }
13
+ public set s(value: string) {
14
+ this._fields.s.value = value
15
+ }
16
+
17
+ // current reading index
18
+ public get i(): number {
19
+ return this._fields.i.value
20
+ }
21
+ public set i(value: number) {
22
+ this._fields.i.value = value
23
+ }
24
+
25
+ // index of previous rune; or < 0
26
+ public get prevRune(): number {
27
+ return this._fields.prevRune.value
28
+ }
29
+ public set prevRune(value: number) {
30
+ this._fields.prevRune.value = value
31
+ }
32
+
33
+ public _fields: {
34
+ s: $.VarRef<string>
35
+ i: $.VarRef<number>
36
+ prevRune: $.VarRef<number>
37
+ }
38
+
39
+ constructor(init?: Partial<{ i?: number; prevRune?: number; s?: string }>) {
40
+ this._fields = {
41
+ s: $.varRef(init?.s ?? ''),
42
+ i: $.varRef(init?.i ?? 0),
43
+ prevRune: $.varRef(init?.prevRune ?? 0),
44
+ }
45
+ }
46
+
47
+ public clone(): Reader {
48
+ const cloned = new Reader()
49
+ cloned._fields = {
50
+ s: $.varRef(this._fields.s.value),
51
+ i: $.varRef(this._fields.i.value),
52
+ prevRune: $.varRef(this._fields.prevRune.value),
53
+ }
54
+ return cloned
55
+ }
56
+
57
+ // Len returns the number of bytes of the unread portion of the
58
+ // string.
59
+ public Len(): number {
60
+ const r = this
61
+ if (r!.i >= ($.len(r!.s) as number)) {
62
+ return 0
63
+ }
64
+ return (($.len(r!.s) as number) - r!.i) as number
65
+ }
66
+
67
+ // Size returns the original length of the underlying string.
68
+ // Size is the number of bytes available for reading via [Reader.ReadAt].
69
+ // The returned value is always the same and is not affected by calls
70
+ // to any other method.
71
+ public Size(): number {
72
+ const r = this
73
+ return $.len(r!.s) as number
74
+ }
75
+
76
+ // Read implements the [io.Reader] interface.
77
+ public Read(b: Uint8Array): [number, $.GoError] {
78
+ const r = this
79
+ if (r!.i >= ($.len(r!.s) as number)) {
80
+ return [0, io.EOF]
81
+ }
82
+ r!.prevRune = -1
83
+ let n = $.copy(b, $.sliceString(r!.s, r!.i, undefined))
84
+ r!.i += n as number
85
+ let err: $.GoError = null
86
+ return [n, err]
87
+ }
88
+
89
+ // ReadAt implements the [io.ReaderAt] interface.
90
+ public ReadAt(b: Uint8Array, off: number): [number, $.GoError] {
91
+ const r = this
92
+ if (off < 0) {
93
+ return [0, errors.New('strings.Reader.ReadAt: negative offset')]
94
+ }
95
+ if (off >= ($.len(r!.s) as number)) {
96
+ return [0, io.EOF]
97
+ }
98
+ let n = $.copy(b, $.sliceString(r!.s, off, undefined))
99
+ let err: $.GoError = null
100
+ if (n < $.len(b)) {
101
+ err = io.EOF
102
+ }
103
+ return [n, err]
104
+ }
105
+
106
+ // ReadByte implements the [io.ByteReader] interface.
107
+ public ReadByte(): [number, $.GoError] {
108
+ const r = this
109
+ r!.prevRune = -1
110
+ if (r!.i >= ($.len(r!.s) as number)) {
111
+ return [0, io.EOF]
112
+ }
113
+ let b = $.indexString(r!.s, r!.i)
114
+ r!.i++
115
+ return [b, null]
116
+ }
117
+
118
+ // UnreadByte implements the [io.ByteScanner] interface.
119
+ public UnreadByte(): $.GoError {
120
+ const r = this
121
+ if (r!.i <= 0) {
122
+ return errors.New('strings.Reader.UnreadByte: at beginning of string')
123
+ }
124
+ r!.prevRune = -1
125
+ r!.i--
126
+ return null
127
+ }
128
+
129
+ // ReadRune implements the [io.RuneReader] interface.
130
+ public ReadRune(): [number, number, $.GoError] {
131
+ const r = this
132
+ if (r!.i >= ($.len(r!.s) as number)) {
133
+ r!.prevRune = -1
134
+ return [0, 0, io.EOF]
135
+ }
136
+ r!.prevRune = r!.i as number
137
+ {
138
+ let c = $.indexString(r!.s, r!.i)
139
+ if (c < utf8.RuneSelf) {
140
+ r!.i++
141
+ return [c as number, 1, null]
142
+ }
143
+ }
144
+ let ch: number, size: number
145
+ ;[ch, size] = utf8.DecodeRuneInString($.sliceString(r!.s, r!.i, undefined))
146
+ r!.i += size as number
147
+ return [ch, size, null]
148
+ }
149
+
150
+ // UnreadRune implements the [io.RuneScanner] interface.
151
+ public UnreadRune(): $.GoError {
152
+ const r = this
153
+ if (r!.i <= 0) {
154
+ return errors.New('strings.Reader.UnreadRune: at beginning of string')
155
+ }
156
+ if (r!.prevRune < 0) {
157
+ return errors.New(
158
+ 'strings.Reader.UnreadRune: previous operation was not ReadRune',
159
+ )
160
+ }
161
+ r!.i = r!.prevRune as number
162
+ r!.prevRune = -1
163
+ return null
164
+ }
165
+
166
+ // Seek implements the [io.Seeker] interface.
167
+ public Seek(offset: number, whence: number): [number, $.GoError] {
168
+ const r = this
169
+ r!.prevRune = -1
170
+ let abs: number = 0
171
+ switch (whence) {
172
+ case io.SeekStart:
173
+ abs = offset
174
+ break
175
+ case io.SeekCurrent:
176
+ abs = r!.i + offset
177
+ break
178
+ case io.SeekEnd:
179
+ abs = ($.len(r!.s) as number) + offset
180
+ break
181
+ default:
182
+ return [0, errors.New('strings.Reader.Seek: invalid whence')]
183
+ break
184
+ }
185
+ if (abs < 0) {
186
+ return [0, errors.New('strings.Reader.Seek: negative position')]
187
+ }
188
+ r!.i = abs
189
+ return [abs, null]
190
+ }
191
+
192
+ // WriteTo implements the [io.WriterTo] interface.
193
+ public WriteTo(w: io.Writer): [number, $.GoError] {
194
+ const r = this
195
+ r!.prevRune = -1
196
+ if (r!.i >= ($.len(r!.s) as number)) {
197
+ return [0, null]
198
+ }
199
+ let s = $.sliceString(r!.s, r!.i, undefined)
200
+ let m: number
201
+ let err: $.GoError
202
+ ;[m, err] = io.WriteString(w, s)
203
+ if (m > $.len(s)) {
204
+ $.panic('strings.Reader.WriteTo: invalid WriteString count')
205
+ }
206
+ r!.i += m as number
207
+ let n = m as number
208
+ if (m != $.len(s) && err == null) {
209
+ err = io.ErrShortWrite
210
+ }
211
+ return [n, err]
212
+ }
213
+
214
+ // Reset resets the [Reader] to be reading from s.
215
+ public Reset(s: string): void {
216
+ const r = this
217
+ r!.s = s
218
+ r!.i = 0
219
+ r!.prevRune = -1
220
+ }
221
+
222
+ // Register this type with the runtime type system
223
+ static __typeInfo = $.registerStructType(
224
+ 'Reader',
225
+ new Reader(),
226
+ [
227
+ {
228
+ name: 'Len',
229
+ args: [],
230
+ returns: [{ type: { kind: $.TypeKind.Basic, name: 'number' } }],
231
+ },
232
+ {
233
+ name: 'Size',
234
+ args: [],
235
+ returns: [{ type: { kind: $.TypeKind.Basic, name: 'number' } }],
236
+ },
237
+ {
238
+ name: 'Read',
239
+ args: [
240
+ {
241
+ name: 'b',
242
+ type: {
243
+ kind: $.TypeKind.Slice,
244
+ elemType: { kind: $.TypeKind.Basic, name: 'number' },
245
+ },
246
+ },
247
+ ],
248
+ returns: [
249
+ { type: { kind: $.TypeKind.Basic, name: 'number' } },
250
+ {
251
+ type: {
252
+ kind: $.TypeKind.Interface,
253
+ name: 'GoError',
254
+ methods: [
255
+ {
256
+ name: 'Error',
257
+ args: [],
258
+ returns: [
259
+ { type: { kind: $.TypeKind.Basic, name: 'string' } },
260
+ ],
261
+ },
262
+ ],
263
+ },
264
+ },
265
+ ],
266
+ },
267
+ {
268
+ name: 'ReadAt',
269
+ args: [
270
+ {
271
+ name: 'b',
272
+ type: {
273
+ kind: $.TypeKind.Slice,
274
+ elemType: { kind: $.TypeKind.Basic, name: 'number' },
275
+ },
276
+ },
277
+ { name: 'off', type: { kind: $.TypeKind.Basic, name: 'number' } },
278
+ ],
279
+ returns: [
280
+ { type: { kind: $.TypeKind.Basic, name: 'number' } },
281
+ {
282
+ type: {
283
+ kind: $.TypeKind.Interface,
284
+ name: 'GoError',
285
+ methods: [
286
+ {
287
+ name: 'Error',
288
+ args: [],
289
+ returns: [
290
+ { type: { kind: $.TypeKind.Basic, name: 'string' } },
291
+ ],
292
+ },
293
+ ],
294
+ },
295
+ },
296
+ ],
297
+ },
298
+ {
299
+ name: 'ReadByte',
300
+ args: [],
301
+ returns: [
302
+ { type: { kind: $.TypeKind.Basic, name: 'number' } },
303
+ {
304
+ type: {
305
+ kind: $.TypeKind.Interface,
306
+ name: 'GoError',
307
+ methods: [
308
+ {
309
+ name: 'Error',
310
+ args: [],
311
+ returns: [
312
+ { type: { kind: $.TypeKind.Basic, name: 'string' } },
313
+ ],
314
+ },
315
+ ],
316
+ },
317
+ },
318
+ ],
319
+ },
320
+ {
321
+ name: 'UnreadByte',
322
+ args: [],
323
+ returns: [
324
+ {
325
+ type: {
326
+ kind: $.TypeKind.Interface,
327
+ name: 'GoError',
328
+ methods: [
329
+ {
330
+ name: 'Error',
331
+ args: [],
332
+ returns: [
333
+ { type: { kind: $.TypeKind.Basic, name: 'string' } },
334
+ ],
335
+ },
336
+ ],
337
+ },
338
+ },
339
+ ],
340
+ },
341
+ {
342
+ name: 'ReadRune',
343
+ args: [],
344
+ returns: [
345
+ { type: { kind: $.TypeKind.Basic, name: 'number' } },
346
+ { type: { kind: $.TypeKind.Basic, name: 'number' } },
347
+ {
348
+ type: {
349
+ kind: $.TypeKind.Interface,
350
+ name: 'GoError',
351
+ methods: [
352
+ {
353
+ name: 'Error',
354
+ args: [],
355
+ returns: [
356
+ { type: { kind: $.TypeKind.Basic, name: 'string' } },
357
+ ],
358
+ },
359
+ ],
360
+ },
361
+ },
362
+ ],
363
+ },
364
+ {
365
+ name: 'UnreadRune',
366
+ args: [],
367
+ returns: [
368
+ {
369
+ type: {
370
+ kind: $.TypeKind.Interface,
371
+ name: 'GoError',
372
+ methods: [
373
+ {
374
+ name: 'Error',
375
+ args: [],
376
+ returns: [
377
+ { type: { kind: $.TypeKind.Basic, name: 'string' } },
378
+ ],
379
+ },
380
+ ],
381
+ },
382
+ },
383
+ ],
384
+ },
385
+ {
386
+ name: 'Seek',
387
+ args: [
388
+ { name: 'offset', type: { kind: $.TypeKind.Basic, name: 'number' } },
389
+ { name: 'whence', type: { kind: $.TypeKind.Basic, name: 'number' } },
390
+ ],
391
+ returns: [
392
+ { type: { kind: $.TypeKind.Basic, name: 'number' } },
393
+ {
394
+ type: {
395
+ kind: $.TypeKind.Interface,
396
+ name: 'GoError',
397
+ methods: [
398
+ {
399
+ name: 'Error',
400
+ args: [],
401
+ returns: [
402
+ { type: { kind: $.TypeKind.Basic, name: 'string' } },
403
+ ],
404
+ },
405
+ ],
406
+ },
407
+ },
408
+ ],
409
+ },
410
+ {
411
+ name: 'WriteTo',
412
+ args: [{ name: 'w', type: 'Writer' }],
413
+ returns: [
414
+ { type: { kind: $.TypeKind.Basic, name: 'number' } },
415
+ {
416
+ type: {
417
+ kind: $.TypeKind.Interface,
418
+ name: 'GoError',
419
+ methods: [
420
+ {
421
+ name: 'Error',
422
+ args: [],
423
+ returns: [
424
+ { type: { kind: $.TypeKind.Basic, name: 'string' } },
425
+ ],
426
+ },
427
+ ],
428
+ },
429
+ },
430
+ ],
431
+ },
432
+ {
433
+ name: 'Reset',
434
+ args: [{ name: 's', type: { kind: $.TypeKind.Basic, name: 'string' } }],
435
+ returns: [],
436
+ },
437
+ ],
438
+ Reader,
439
+ {
440
+ s: { kind: $.TypeKind.Basic, name: 'string' },
441
+ i: { kind: $.TypeKind.Basic, name: 'number' },
442
+ prevRune: { kind: $.TypeKind.Basic, name: 'number' },
443
+ },
444
+ )
445
+ }
446
+
447
+ // NewReader returns a new [Reader] reading from s.
448
+ // It is similar to [bytes.NewBufferString] but more efficient and non-writable.
449
+ export function NewReader(s: string): Reader | null {
450
+ return new Reader({ s: s })
451
+ }