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
@@ -0,0 +1,1310 @@
1
+ import * as $ from '@goscript/builtin/builtin.js'
2
+ import { makeStringFinder, stringFinder } from './search.js'
3
+ import { Count, HasPrefix } from './strings.js'
4
+ import { Builder } from './builder.js'
5
+ import * as io from '@goscript/io/index.js'
6
+
7
+ export class Replacer {
8
+ // guards buildOnce method
9
+ public get built(): boolean {
10
+ return this._fields.built.value
11
+ }
12
+ public set built(value: boolean) {
13
+ this._fields.built.value = value
14
+ }
15
+
16
+ public get r(): replacer {
17
+ return this._fields.r.value
18
+ }
19
+ public set r(value: replacer) {
20
+ this._fields.r.value = value
21
+ }
22
+
23
+ public get oldnew(): $.Slice<string> {
24
+ return this._fields.oldnew.value
25
+ }
26
+ public set oldnew(value: $.Slice<string>) {
27
+ this._fields.oldnew.value = value
28
+ }
29
+
30
+ public _fields: {
31
+ built: $.VarRef<boolean>
32
+ r: $.VarRef<replacer>
33
+ oldnew: $.VarRef<$.Slice<string>>
34
+ }
35
+
36
+ constructor(
37
+ init?: Partial<{
38
+ oldnew?: $.Slice<string>
39
+ built?: boolean
40
+ r?: replacer
41
+ }>,
42
+ ) {
43
+ this._fields = {
44
+ built: $.varRef(init?.built ?? false),
45
+ r: $.varRef(init?.r ?? null),
46
+ oldnew: $.varRef(init?.oldnew ?? null),
47
+ }
48
+ }
49
+
50
+ public clone(): Replacer {
51
+ const cloned = new Replacer()
52
+ cloned._fields = {
53
+ built: $.varRef(this._fields.built.value),
54
+ r: $.varRef(this._fields.r.value),
55
+ oldnew: $.varRef(this._fields.oldnew.value),
56
+ }
57
+ return cloned
58
+ }
59
+
60
+ public buildOnce(): void {
61
+ if (this.built) {
62
+ return
63
+ }
64
+ const r = this
65
+ const built = r.build()
66
+ r.r = built
67
+ r.oldnew = null
68
+ r.built = true
69
+ }
70
+
71
+ public build(): replacer {
72
+ const b = this
73
+ let oldnew = b!.oldnew
74
+
75
+ // Handle empty case - no replacements to do
76
+ if ($.len(oldnew) == 0) {
77
+ return {
78
+ Replace: (s: string): string => s,
79
+ WriteString: (w: io.Writer, s: string): [number, $.GoError] => {
80
+ const bytes = $.stringToBytes(s)
81
+ return w.Write(bytes)
82
+ },
83
+ }
84
+ }
85
+
86
+ if ($.len(oldnew) == 2 && $.len(oldnew![0]) > 1) {
87
+ return makeSingleStringReplacer(oldnew![0], oldnew![1])
88
+ }
89
+ let allNewBytes = true
90
+ for (let i = 0; i < $.len(oldnew); i += 2) {
91
+ if ($.len(oldnew![i]) != 1) {
92
+ return makeGenericReplacer(oldnew)
93
+ }
94
+ if ($.len(oldnew![i + 1]) != 1) {
95
+ allNewBytes = false
96
+ }
97
+ }
98
+ if (allNewBytes) {
99
+ let r: number[] = new Array(256)
100
+ for (let i = 0; i < r.length; i++) {
101
+ r[i] = i
102
+ }
103
+ // The first occurrence of old->new map takes precedence
104
+ // over the others with the same old string.
105
+ for (let i = $.len(oldnew) - 2; i >= 0; i -= 2) {
106
+ let o = $.indexString(oldnew![i], 0)
107
+ let n = $.indexString(oldnew![i + 1], 0)
108
+ r[o] = n
109
+ }
110
+ return {
111
+ Replace: (s: string): string => {
112
+ let result = ''
113
+ for (let i = 0; i < s.length; i++) {
114
+ const charCode = s.charCodeAt(i)
115
+ if (charCode < 256) {
116
+ result += String.fromCharCode(r[charCode])
117
+ } else {
118
+ result += s[i]
119
+ }
120
+ }
121
+ return result
122
+ },
123
+ WriteString: (w: io.Writer, s: string): [number, $.GoError] => {
124
+ const replaced = this.Replace(s)
125
+ const bytes = $.stringToBytes(replaced)
126
+ return w.Write(bytes)
127
+ },
128
+ }
129
+ }
130
+ let r = new byteStringReplacer({
131
+ toReplace: $.makeSlice<string>(0, $.len(oldnew) / 2),
132
+ })
133
+ for (let i = $.len(oldnew) - 2; i >= 0; i -= 2) {
134
+ let o = $.indexString(oldnew![i], 0)
135
+ let n = oldnew![i + 1]
136
+ // To avoid counting repetitions multiple times.
137
+
138
+ // We need to use string([]byte{o}) instead of string(o),
139
+ // to avoid utf8 encoding of o.
140
+ // E. g. byte(150) produces string of length 2.
141
+ if (r.replacements![o] == null) {
142
+ // We need to use string([]byte{o}) instead of string(o),
143
+ // to avoid utf8 encoding of o.
144
+ // E. g. byte(150) produces string of length 2.
145
+ r.toReplace = $.append(
146
+ r.toReplace,
147
+ $.bytesToString(new Uint8Array([o])),
148
+ )
149
+ }
150
+ r.replacements![o] = $.stringToBytes(n)
151
+ }
152
+ return r
153
+ }
154
+
155
+ // Replace returns a copy of s with all replacements performed.
156
+ public Replace(s: string): string {
157
+ const r = this
158
+ r.buildOnce()
159
+ return r.r!.Replace(s)
160
+ }
161
+
162
+ // WriteString writes s to w with all replacements performed.
163
+ public WriteString(w: io.Writer, s: string): [number, $.GoError] {
164
+ const r = this
165
+ r.buildOnce()
166
+ return r.r!.WriteString(w, s)
167
+ }
168
+
169
+ // Register this type with the runtime type system
170
+ static __typeInfo = $.registerStructType(
171
+ 'Replacer',
172
+ new Replacer(),
173
+ [
174
+ { name: 'buildOnce', args: [], returns: [] },
175
+ { name: 'build', args: [], returns: [{ type: 'replacer' }] },
176
+ {
177
+ name: 'Replace',
178
+ args: [{ name: 's', type: { kind: $.TypeKind.Basic, name: 'string' } }],
179
+ returns: [{ type: { kind: $.TypeKind.Basic, name: 'string' } }],
180
+ },
181
+ {
182
+ name: 'WriteString',
183
+ args: [
184
+ { name: 'w', type: 'Writer' },
185
+ { name: 's', type: { kind: $.TypeKind.Basic, name: 'string' } },
186
+ ],
187
+ returns: [
188
+ { type: { kind: $.TypeKind.Basic, name: 'number' } },
189
+ {
190
+ type: {
191
+ kind: $.TypeKind.Interface,
192
+ name: 'GoError',
193
+ methods: [
194
+ {
195
+ name: 'Error',
196
+ args: [],
197
+ returns: [
198
+ { type: { kind: $.TypeKind.Basic, name: 'string' } },
199
+ ],
200
+ },
201
+ ],
202
+ },
203
+ },
204
+ ],
205
+ },
206
+ ],
207
+ Replacer,
208
+ {
209
+ built: { kind: $.TypeKind.Basic, name: 'boolean' },
210
+ r: 'replacer',
211
+ oldnew: {
212
+ kind: $.TypeKind.Slice,
213
+ elemType: { kind: $.TypeKind.Basic, name: 'string' },
214
+ },
215
+ },
216
+ )
217
+ }
218
+
219
+ type replacer = null | {
220
+ Replace(s: string): string
221
+ WriteString(w: io.Writer, s: string): [number, $.GoError]
222
+ }
223
+
224
+ $.registerInterfaceType(
225
+ 'replacer',
226
+ null, // Zero value for interface is null
227
+ [
228
+ {
229
+ name: 'Replace',
230
+ args: [{ name: 's', type: { kind: $.TypeKind.Basic, name: 'string' } }],
231
+ returns: [{ type: { kind: $.TypeKind.Basic, name: 'string' } }],
232
+ },
233
+ {
234
+ name: 'WriteString',
235
+ args: [
236
+ { name: 'w', type: 'Writer' },
237
+ { name: 's', type: { kind: $.TypeKind.Basic, name: 'string' } },
238
+ ],
239
+ returns: [
240
+ { type: { kind: $.TypeKind.Basic, name: 'number' } },
241
+ {
242
+ type: {
243
+ kind: $.TypeKind.Interface,
244
+ name: 'GoError',
245
+ methods: [
246
+ {
247
+ name: 'Error',
248
+ args: [],
249
+ returns: [{ type: { kind: $.TypeKind.Basic, name: 'string' } }],
250
+ },
251
+ ],
252
+ },
253
+ },
254
+ ],
255
+ },
256
+ ],
257
+ )
258
+
259
+ // NewReplacer returns a new [Replacer] from a list of old, new string
260
+ // pairs. Replacements are performed in the order they appear in the
261
+ // target string, without overlapping matches. The old string
262
+ // comparisons are done in argument order.
263
+ //
264
+ // NewReplacer panics if given an odd number of arguments.
265
+ export function NewReplacer(...oldnew: string[]): Replacer | null {
266
+ if ($.len(oldnew) % 2 == 1) {
267
+ $.panic('strings.NewReplacer: odd argument count')
268
+ }
269
+ return new Replacer({ oldnew: $.append(null, ...oldnew) })
270
+ }
271
+
272
+ class trieNode {
273
+ // value is the value of the trie node's key/value pair. It is empty if
274
+ // this node is not a complete key.
275
+ public get value(): string {
276
+ return this._fields.value.value
277
+ }
278
+ public set value(value: string) {
279
+ this._fields.value.value = value
280
+ }
281
+
282
+ // priority is the priority (higher is more important) of the trie node's
283
+ // key/value pair; keys are not necessarily matched shortest- or longest-
284
+ // first. Priority is positive if this node is a complete key, and zero
285
+ // otherwise. In the example above, positive/zero priorities are marked
286
+ // with a trailing "+" or "-".
287
+ public get priority(): number {
288
+ return this._fields.priority.value
289
+ }
290
+ public set priority(value: number) {
291
+ this._fields.priority.value = value
292
+ }
293
+
294
+ // prefix is the difference in keys between this trie node and the next.
295
+ // In the example above, node n4 has prefix "cbc" and n4's next node is n5.
296
+ // Node n5 has no children and so has zero prefix, next and table fields.
297
+ public get prefix(): string {
298
+ return this._fields.prefix.value
299
+ }
300
+ public set prefix(value: string) {
301
+ this._fields.prefix.value = value
302
+ }
303
+
304
+ public get next(): trieNode | null {
305
+ return this._fields.next.value
306
+ }
307
+ public set next(value: trieNode | null) {
308
+ this._fields.next.value = value
309
+ }
310
+
311
+ // table is a lookup table indexed by the next byte in the key, after
312
+ // remapping that byte through genericReplacer.mapping to create a dense
313
+ // index. In the example above, the keys only use 'a', 'b', 'c', 'x' and
314
+ // 'y', which remap to 0, 1, 2, 3 and 4. All other bytes remap to 5, and
315
+ // genericReplacer.tableSize will be 5. Node n0's table will be
316
+ // []*trieNode{ 0:n1, 1:n4, 3:n6 }, where the 0, 1 and 3 are the remapped
317
+ // 'a', 'b' and 'x'.
318
+ public get table(): $.Slice<trieNode | null> {
319
+ return this._fields.table.value
320
+ }
321
+ public set table(value: $.Slice<trieNode | null>) {
322
+ this._fields.table.value = value
323
+ }
324
+
325
+ public _fields: {
326
+ value: $.VarRef<string>
327
+ priority: $.VarRef<number>
328
+ prefix: $.VarRef<string>
329
+ next: $.VarRef<trieNode | null>
330
+ table: $.VarRef<$.Slice<trieNode | null>>
331
+ }
332
+
333
+ constructor(
334
+ init?: Partial<{
335
+ next?: trieNode | null
336
+ prefix?: string
337
+ priority?: number
338
+ table?: $.Slice<trieNode | null>
339
+ value?: string
340
+ }>,
341
+ ) {
342
+ this._fields = {
343
+ value: $.varRef(init?.value ?? ''),
344
+ priority: $.varRef(init?.priority ?? 0),
345
+ prefix: $.varRef(init?.prefix ?? ''),
346
+ next: $.varRef(init?.next ?? null),
347
+ table: $.varRef(init?.table ?? null),
348
+ }
349
+ }
350
+
351
+ public clone(): trieNode {
352
+ const cloned = new trieNode()
353
+ cloned._fields = {
354
+ value: $.varRef(this._fields.value.value),
355
+ priority: $.varRef(this._fields.priority.value),
356
+ prefix: $.varRef(this._fields.prefix.value),
357
+ next: $.varRef(this._fields.next.value),
358
+ table: $.varRef(this._fields.table.value),
359
+ }
360
+ return cloned
361
+ }
362
+
363
+ public add(
364
+ key: string,
365
+ val: string,
366
+ priority: number,
367
+ r: genericReplacer | null,
368
+ ): void {
369
+ const t = this
370
+ if (key == '') {
371
+ if (t!.priority == 0) {
372
+ t!.value = val
373
+ t!.priority = priority
374
+ }
375
+ return
376
+ }
377
+ if (t!.prefix != '') {
378
+ // Need to split the prefix among multiple nodes.
379
+ // length of the longest common prefix
380
+ let n: number = 0
381
+ for (; n < $.len(t!.prefix) && n < $.len(key); n++) {
382
+ if ($.indexString(t!.prefix, n) != $.indexString(key, n)) {
383
+ break
384
+ }
385
+ }
386
+
387
+ // First byte differs, start a new lookup table here. Looking up
388
+ // what is currently t.prefix[0] will lead to prefixNode, and
389
+ // looking up key[0] will lead to keyNode.
390
+
391
+ // Insert new node after the common section of the prefix.
392
+ if (n == $.len(t!.prefix)) {
393
+ t!.next!.add($.sliceString(key, n, undefined), val, priority, r)
394
+ } else if (n == 0) {
395
+ // First byte differs, start a new lookup table here. Looking up
396
+ // what is currently t.prefix[0] will lead to prefixNode, and
397
+ // looking up key[0] will lead to keyNode.
398
+ let prefixNode: trieNode | null = null
399
+ if ($.len(t!.prefix) == 1) {
400
+ prefixNode = t!.next
401
+ } else {
402
+ prefixNode = new trieNode({
403
+ next: t!.next,
404
+ prefix: $.sliceString(t!.prefix, 1, undefined),
405
+ })
406
+ }
407
+ let keyNode = new trieNode()
408
+ t!.table = $.makeSlice<trieNode | null>(r!.tableSize)
409
+ t!.table![r!.mapping![$.indexString(t!.prefix, 0)]] = prefixNode
410
+ t!.table![r!.mapping![$.indexString(key, 0)]] = keyNode
411
+ t!.prefix = ''
412
+ t!.next = null
413
+ keyNode!.add($.sliceString(key, 1, undefined), val, priority, r)
414
+ } else {
415
+ // Insert new node after the common section of the prefix.
416
+ let next = new trieNode({
417
+ next: t!.next,
418
+ prefix: $.sliceString(t!.prefix, n, undefined),
419
+ })
420
+ t!.prefix = $.sliceString(t!.prefix, undefined, n)
421
+ t!.next = next
422
+ next!.add($.sliceString(key, n, undefined), val, priority, r)
423
+ }
424
+ } else if (t!.table != null) {
425
+ // Insert into existing table.
426
+ let m = r!.mapping![$.indexString(key, 0)]
427
+ if (t!.table![m] == null) {
428
+ t!.table![m] = new trieNode()
429
+ }
430
+ t!.table![m]!.add($.sliceString(key, 1, undefined), val, priority, r)
431
+ } else {
432
+ t!.prefix = key
433
+ t!.next = new trieNode()
434
+ t!.next!.add('', val, priority, r)
435
+ }
436
+ }
437
+
438
+ // Register this type with the runtime type system
439
+ static __typeInfo = $.registerStructType(
440
+ 'trieNode',
441
+ new trieNode(),
442
+ [
443
+ {
444
+ name: 'add',
445
+ args: [
446
+ { name: 'key', type: { kind: $.TypeKind.Basic, name: 'string' } },
447
+ { name: 'val', type: { kind: $.TypeKind.Basic, name: 'string' } },
448
+ {
449
+ name: 'priority',
450
+ type: { kind: $.TypeKind.Basic, name: 'number' },
451
+ },
452
+ {
453
+ name: 'r',
454
+ type: { kind: $.TypeKind.Pointer, elemType: 'genericReplacer' },
455
+ },
456
+ ],
457
+ returns: [],
458
+ },
459
+ ],
460
+ trieNode,
461
+ {
462
+ value: { kind: $.TypeKind.Basic, name: 'string' },
463
+ priority: { kind: $.TypeKind.Basic, name: 'number' },
464
+ prefix: { kind: $.TypeKind.Basic, name: 'string' },
465
+ next: { kind: $.TypeKind.Pointer, elemType: 'trieNode' },
466
+ table: {
467
+ kind: $.TypeKind.Slice,
468
+ elemType: { kind: $.TypeKind.Pointer, elemType: 'trieNode' },
469
+ },
470
+ },
471
+ )
472
+ }
473
+
474
+ class genericReplacer {
475
+ public get root(): trieNode {
476
+ return this._fields.root.value
477
+ }
478
+ public set root(value: trieNode) {
479
+ this._fields.root.value = value
480
+ }
481
+
482
+ // tableSize is the size of a trie node's lookup table. It is the number
483
+ // of unique key bytes.
484
+ public get tableSize(): number {
485
+ return this._fields.tableSize.value
486
+ }
487
+ public set tableSize(value: number) {
488
+ this._fields.tableSize.value = value
489
+ }
490
+
491
+ // mapping maps from key bytes to a dense index for trieNode.table.
492
+ public get mapping(): number[] {
493
+ return this._fields.mapping.value
494
+ }
495
+ public set mapping(value: number[]) {
496
+ this._fields.mapping.value = value
497
+ }
498
+
499
+ public _fields: {
500
+ root: $.VarRef<trieNode>
501
+ tableSize: $.VarRef<number>
502
+ mapping: $.VarRef<number[]>
503
+ }
504
+
505
+ constructor(
506
+ init?: Partial<{ mapping?: number[]; root?: trieNode; tableSize?: number }>,
507
+ ) {
508
+ this._fields = {
509
+ root: $.varRef(init?.root?.clone() ?? new trieNode()),
510
+ tableSize: $.varRef(init?.tableSize ?? 0),
511
+ mapping: $.varRef(
512
+ init?.mapping ?? [
513
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
514
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
515
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
516
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
517
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
518
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
519
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
520
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
521
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
522
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
523
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
524
+ 0, 0, 0,
525
+ ],
526
+ ),
527
+ }
528
+ }
529
+
530
+ public clone(): genericReplacer {
531
+ const cloned = new genericReplacer()
532
+ cloned._fields = {
533
+ root: $.varRef(this._fields.root.value?.clone() ?? null),
534
+ tableSize: $.varRef(this._fields.tableSize.value),
535
+ mapping: $.varRef(this._fields.mapping.value),
536
+ }
537
+ return cloned
538
+ }
539
+
540
+ public lookup(s: string, ignoreRoot: boolean): [string, number, boolean] {
541
+ const r = this
542
+ let bestPriority = 0
543
+ let node = r!.root
544
+ let n = 0
545
+ let val: string = ''
546
+ let keylen: number = 0
547
+ let found: boolean = false
548
+ for (; node != null; ) {
549
+ if (node!.priority > bestPriority && !(ignoreRoot && node === r!.root)) {
550
+ bestPriority = node!.priority
551
+ val = node!.value
552
+ keylen = n
553
+ found = true
554
+ }
555
+
556
+ if (s == '') {
557
+ break
558
+ }
559
+ if (node!.table != null) {
560
+ let index = r!.mapping![$.indexString(s, 0)]
561
+ if ((index as number) == r!.tableSize) {
562
+ break
563
+ }
564
+ node = node!.table![index]!
565
+ s = $.sliceString(s, 1, undefined)
566
+ n++
567
+ } else if (node!.prefix != '' && HasPrefix(s, node!.prefix)) {
568
+ n += $.len(node!.prefix)
569
+ s = $.sliceString(s, $.len(node!.prefix), undefined)
570
+ node = node!.next!
571
+ } else {
572
+ break
573
+ }
574
+ }
575
+ return [val, keylen, found]
576
+ }
577
+
578
+ public Replace(s: string): string {
579
+ const r = this
580
+ let result = ''
581
+ let last = 0
582
+ for (let i = 0; i <= $.len(s); ) {
583
+ // Fast path: s[i] is not a prefix of any pattern.
584
+ if (i != $.len(s) && r!.root.priority == 0) {
585
+ let index = r!.mapping![$.indexString(s, i)] as number
586
+ if (index == r!.tableSize || r!.root.table![index] == null) {
587
+ i++
588
+ continue
589
+ }
590
+ }
591
+
592
+ // Ignore the empty match iff the previous loop found the empty match.
593
+ let [val, keylen, match] = r!.lookup(
594
+ $.sliceString(s, i, undefined),
595
+ false,
596
+ )
597
+ if (match) {
598
+ result += $.sliceString(s, last, i)
599
+ result += val
600
+ i += keylen
601
+ last = i
602
+ continue
603
+ }
604
+ i++
605
+ }
606
+ if (last != $.len(s)) {
607
+ result += $.sliceString(s, last, undefined)
608
+ }
609
+ return result
610
+ }
611
+
612
+ public WriteString(w: io.Writer, s: string): [number, $.GoError] {
613
+ const r = this
614
+ let sw = getStringWriter(w)
615
+ let last: number = 0
616
+ let wn: number = 0
617
+ let n: number = 0
618
+ let err: $.GoError | null = null
619
+ let prevMatchEmpty: boolean = false
620
+ for (let i = 0; i <= $.len(s); ) {
621
+ // Fast path: s[i] is not a prefix of any pattern.
622
+ if (i != $.len(s) && r!.root.priority == 0) {
623
+ let index = r!.mapping![$.indexString(s, i)] as number
624
+ if (index == r!.tableSize || r!.root.table![index] == null) {
625
+ i++
626
+ continue
627
+ }
628
+ }
629
+
630
+ // Ignore the empty match iff the previous loop found the empty match.
631
+ let [val, keylen, match] = r!.lookup(
632
+ $.sliceString(s, i, undefined),
633
+ prevMatchEmpty,
634
+ )
635
+ prevMatchEmpty = match && keylen == 0
636
+ if (match) {
637
+ ;[wn, err] = sw!.WriteString($.sliceString(s, last, i))
638
+ n += wn
639
+ if (err != null) {
640
+ return [n, err]
641
+ }
642
+ ;[wn, err] = sw!.WriteString(val)
643
+ n += wn
644
+ if (err != null) {
645
+ return [n, err]
646
+ }
647
+ i += keylen
648
+ last = i
649
+ continue
650
+ }
651
+ i++
652
+ }
653
+ if (last != $.len(s)) {
654
+ ;[wn, err] = sw!.WriteString($.sliceString(s, last, undefined))
655
+ n += wn
656
+ }
657
+ return [n, err]
658
+ }
659
+
660
+ // Register this type with the runtime type system
661
+ static __typeInfo = $.registerStructType(
662
+ 'genericReplacer',
663
+ new genericReplacer(),
664
+ [
665
+ {
666
+ name: 'lookup',
667
+ args: [
668
+ { name: 's', type: { kind: $.TypeKind.Basic, name: 'string' } },
669
+ {
670
+ name: 'ignoreRoot',
671
+ type: { kind: $.TypeKind.Basic, name: 'boolean' },
672
+ },
673
+ ],
674
+ returns: [
675
+ { type: { kind: $.TypeKind.Basic, name: 'string' } },
676
+ { type: { kind: $.TypeKind.Basic, name: 'number' } },
677
+ { type: { kind: $.TypeKind.Basic, name: 'boolean' } },
678
+ ],
679
+ },
680
+ {
681
+ name: 'Replace',
682
+ args: [{ name: 's', type: { kind: $.TypeKind.Basic, name: 'string' } }],
683
+ returns: [{ type: { kind: $.TypeKind.Basic, name: 'string' } }],
684
+ },
685
+ {
686
+ name: 'WriteString',
687
+ args: [
688
+ { name: 'w', type: 'Writer' },
689
+ { name: 's', type: { kind: $.TypeKind.Basic, name: 'string' } },
690
+ ],
691
+ returns: [
692
+ { type: { kind: $.TypeKind.Basic, name: 'number' } },
693
+ {
694
+ type: {
695
+ kind: $.TypeKind.Interface,
696
+ name: 'GoError',
697
+ methods: [
698
+ {
699
+ name: 'Error',
700
+ args: [],
701
+ returns: [
702
+ { type: { kind: $.TypeKind.Basic, name: 'string' } },
703
+ ],
704
+ },
705
+ ],
706
+ },
707
+ },
708
+ ],
709
+ },
710
+ ],
711
+ genericReplacer,
712
+ {
713
+ root: 'trieNode',
714
+ tableSize: { kind: $.TypeKind.Basic, name: 'number' },
715
+ mapping: {
716
+ kind: $.TypeKind.Array,
717
+ length: 256,
718
+ elemType: { kind: $.TypeKind.Basic, name: 'number' },
719
+ },
720
+ },
721
+ )
722
+ }
723
+
724
+ export function makeGenericReplacer(
725
+ oldnew: $.Slice<string>,
726
+ ): genericReplacer | null {
727
+ let r = new genericReplacer()
728
+ // Find each byte used, then assign them each an index.
729
+ for (let i = 0; i < $.len(oldnew); i += 2) {
730
+ let key = oldnew![i]
731
+ for (let j = 0; j < $.len(key); j++) {
732
+ r!.mapping![$.indexString(key, j)] = 1
733
+ }
734
+ }
735
+
736
+ for (let _i = 0; _i < $.len(r!.mapping); _i++) {
737
+ const b = r!.mapping![_i]
738
+ {
739
+ r!.tableSize += b as number
740
+ }
741
+ }
742
+
743
+ let index: number = 0
744
+ for (let i = 0; i < $.len(r!.mapping); i++) {
745
+ const b = r!.mapping![i]
746
+ {
747
+ if (b == 0) {
748
+ r!.mapping![i] = $.byte(r!.tableSize)
749
+ } else {
750
+ r!.mapping![i] = index
751
+ index++
752
+ }
753
+ }
754
+ }
755
+ // Ensure root node uses a lookup table (for performance).
756
+ r!.root.table = $.makeSlice<trieNode | null>(r!.tableSize)
757
+
758
+ for (let i = 0; i < $.len(oldnew); i += 2) {
759
+ r!.root.add(oldnew![i], oldnew![i + 1], $.len(oldnew) - i, r)
760
+ }
761
+ return r
762
+ }
763
+
764
+ type appendSliceWriter = Uint8Array
765
+
766
+ class stringWriter {
767
+ public get w(): io.Writer {
768
+ return this._fields.w.value
769
+ }
770
+ public set w(value: io.Writer) {
771
+ this._fields.w.value = value
772
+ }
773
+
774
+ public _fields: {
775
+ w: $.VarRef<io.Writer>
776
+ }
777
+
778
+ constructor(init?: Partial<{ w?: io.Writer }>) {
779
+ this._fields = {
780
+ w: $.varRef(init?.w!),
781
+ }
782
+ }
783
+
784
+ public clone(): stringWriter {
785
+ const cloned = new stringWriter()
786
+ cloned._fields = {
787
+ w: $.varRef(this._fields.w.value),
788
+ }
789
+ return cloned
790
+ }
791
+
792
+ public WriteString(s: string): [number, $.GoError] {
793
+ const w = this
794
+ return w.w!.Write($.stringToBytes(s))
795
+ }
796
+
797
+ // Register this type with the runtime type system
798
+ static __typeInfo = $.registerStructType(
799
+ 'stringWriter',
800
+ new stringWriter(),
801
+ [
802
+ {
803
+ name: 'WriteString',
804
+ args: [{ name: 's', type: { kind: $.TypeKind.Basic, name: 'string' } }],
805
+ returns: [
806
+ { type: { kind: $.TypeKind.Basic, name: 'number' } },
807
+ {
808
+ type: {
809
+ kind: $.TypeKind.Interface,
810
+ name: 'GoError',
811
+ methods: [
812
+ {
813
+ name: 'Error',
814
+ args: [],
815
+ returns: [
816
+ { type: { kind: $.TypeKind.Basic, name: 'string' } },
817
+ ],
818
+ },
819
+ ],
820
+ },
821
+ },
822
+ ],
823
+ },
824
+ ],
825
+ stringWriter,
826
+ { w: 'Writer' },
827
+ )
828
+ }
829
+
830
+ export function getStringWriter(w: io.Writer): io.StringWriter {
831
+ let { value: sw, ok: ok } = $.typeAssert<io.StringWriter>(
832
+ w,
833
+ 'io.StringWriter',
834
+ )
835
+ if (!ok) {
836
+ sw = new stringWriter({ w: w })
837
+ }
838
+ return sw
839
+ }
840
+
841
+ class singleStringReplacer {
842
+ public get finder(): stringFinder | null {
843
+ return this._fields.finder.value
844
+ }
845
+ public set finder(value: stringFinder | null) {
846
+ this._fields.finder.value = value
847
+ }
848
+
849
+ // value is the new string that replaces that pattern when it's found.
850
+ public get value(): string {
851
+ return this._fields.value.value
852
+ }
853
+ public set value(value: string) {
854
+ this._fields.value.value = value
855
+ }
856
+
857
+ public _fields: {
858
+ finder: $.VarRef<stringFinder | null>
859
+ value: $.VarRef<string>
860
+ }
861
+
862
+ constructor(
863
+ init?: Partial<{ finder?: stringFinder | null; value?: string }>,
864
+ ) {
865
+ this._fields = {
866
+ finder: $.varRef(init?.finder ?? null),
867
+ value: $.varRef(init?.value ?? ''),
868
+ }
869
+ }
870
+
871
+ public clone(): singleStringReplacer {
872
+ const cloned = new singleStringReplacer()
873
+ cloned._fields = {
874
+ finder: $.varRef(this._fields.finder.value),
875
+ value: $.varRef(this._fields.value.value),
876
+ }
877
+ return cloned
878
+ }
879
+
880
+ public Replace(s: string): string {
881
+ const r = this
882
+ let buf: Builder = new Builder()
883
+ let [i, matched] = [0, false]
884
+ for (;;) {
885
+ let match = r!.finder!.next($.sliceString(s, i, undefined))
886
+ if (match == -1) {
887
+ break
888
+ }
889
+ matched = true
890
+ buf.Grow(match + $.len(r!.value))
891
+ buf.WriteString($.sliceString(s, i, i + match))
892
+ buf.WriteString(r!.value)
893
+ i += match + $.len(r!.finder!.pattern)
894
+ }
895
+ if (!matched) {
896
+ return s
897
+ }
898
+ buf.WriteString($.sliceString(s, i, undefined))
899
+ return buf.String()
900
+ }
901
+
902
+ public WriteString(w: io.Writer, s: string): [number, $.GoError] {
903
+ const r = this
904
+ let sw = getStringWriter(w)
905
+ let i: number = 0
906
+ let wn: number = 0
907
+ let n: number = 0
908
+ let err: $.GoError | null = null
909
+ for (;;) {
910
+ let match = r!.finder!.next($.sliceString(s, i, undefined))
911
+ if (match == -1) {
912
+ break
913
+ }
914
+ ;[wn, err] = sw!.WriteString($.sliceString(s, i, i + match))
915
+ n += wn
916
+ if (err != null) {
917
+ return [n, err]
918
+ }
919
+ ;[wn, err] = sw!.WriteString(r!.value)
920
+ n += wn
921
+ if (err != null) {
922
+ return [n, err]
923
+ }
924
+ i += match + $.len(r!.finder!.pattern)
925
+ }
926
+ ;[wn, err] = sw!.WriteString($.sliceString(s, i, undefined))
927
+ n += wn
928
+ return [n, err]
929
+ }
930
+
931
+ // Register this type with the runtime type system
932
+ static __typeInfo = $.registerStructType(
933
+ 'singleStringReplacer',
934
+ new singleStringReplacer(),
935
+ [
936
+ {
937
+ name: 'Replace',
938
+ args: [{ name: 's', type: { kind: $.TypeKind.Basic, name: 'string' } }],
939
+ returns: [{ type: { kind: $.TypeKind.Basic, name: 'string' } }],
940
+ },
941
+ {
942
+ name: 'WriteString',
943
+ args: [
944
+ { name: 'w', type: 'Writer' },
945
+ { name: 's', type: { kind: $.TypeKind.Basic, name: 'string' } },
946
+ ],
947
+ returns: [
948
+ { type: { kind: $.TypeKind.Basic, name: 'number' } },
949
+ {
950
+ type: {
951
+ kind: $.TypeKind.Interface,
952
+ name: 'GoError',
953
+ methods: [
954
+ {
955
+ name: 'Error',
956
+ args: [],
957
+ returns: [
958
+ { type: { kind: $.TypeKind.Basic, name: 'string' } },
959
+ ],
960
+ },
961
+ ],
962
+ },
963
+ },
964
+ ],
965
+ },
966
+ ],
967
+ singleStringReplacer,
968
+ {
969
+ finder: { kind: $.TypeKind.Pointer, elemType: 'stringFinder' },
970
+ value: { kind: $.TypeKind.Basic, name: 'string' },
971
+ },
972
+ )
973
+ }
974
+
975
+ export function makeSingleStringReplacer(
976
+ pattern: string,
977
+ value: string,
978
+ ): singleStringReplacer | null {
979
+ return new singleStringReplacer({
980
+ finder: makeStringFinder(pattern),
981
+ value: value,
982
+ })
983
+ }
984
+
985
+ type byteReplacer = number[]
986
+
987
+ class byteStringReplacer {
988
+ // replacements contains replacement byte slices indexed by old byte.
989
+ // A nil []byte means that the old byte should not be replaced.
990
+ public get replacements(): Uint8Array[] {
991
+ return this._fields.replacements.value
992
+ }
993
+ public set replacements(value: Uint8Array[]) {
994
+ this._fields.replacements.value = value
995
+ }
996
+
997
+ // toReplace keeps a list of bytes to replace. Depending on length of toReplace
998
+ // and length of target string it may be faster to use Count, or a plain loop.
999
+ // We store single byte as a string, because Count takes a string.
1000
+ public get toReplace(): $.Slice<string> {
1001
+ return this._fields.toReplace.value
1002
+ }
1003
+ public set toReplace(value: $.Slice<string>) {
1004
+ this._fields.toReplace.value = value
1005
+ }
1006
+
1007
+ public _fields: {
1008
+ replacements: $.VarRef<Uint8Array[]>
1009
+ toReplace: $.VarRef<$.Slice<string>>
1010
+ }
1011
+
1012
+ constructor(
1013
+ init?: Partial<{
1014
+ replacements?: Uint8Array[]
1015
+ toReplace?: $.Slice<string>
1016
+ }>,
1017
+ ) {
1018
+ this._fields = {
1019
+ replacements: $.varRef(
1020
+ init?.replacements ?? [
1021
+ new Uint8Array(0),
1022
+ new Uint8Array(0),
1023
+ new Uint8Array(0),
1024
+ new Uint8Array(0),
1025
+ new Uint8Array(0),
1026
+ new Uint8Array(0),
1027
+ new Uint8Array(0),
1028
+ new Uint8Array(0),
1029
+ new Uint8Array(0),
1030
+ new Uint8Array(0),
1031
+ new Uint8Array(0),
1032
+ new Uint8Array(0),
1033
+ new Uint8Array(0),
1034
+ new Uint8Array(0),
1035
+ new Uint8Array(0),
1036
+ new Uint8Array(0),
1037
+ new Uint8Array(0),
1038
+ new Uint8Array(0),
1039
+ new Uint8Array(0),
1040
+ new Uint8Array(0),
1041
+ new Uint8Array(0),
1042
+ new Uint8Array(0),
1043
+ new Uint8Array(0),
1044
+ new Uint8Array(0),
1045
+ new Uint8Array(0),
1046
+ new Uint8Array(0),
1047
+ new Uint8Array(0),
1048
+ new Uint8Array(0),
1049
+ new Uint8Array(0),
1050
+ new Uint8Array(0),
1051
+ new Uint8Array(0),
1052
+ new Uint8Array(0),
1053
+ new Uint8Array(0),
1054
+ new Uint8Array(0),
1055
+ new Uint8Array(0),
1056
+ new Uint8Array(0),
1057
+ new Uint8Array(0),
1058
+ new Uint8Array(0),
1059
+ new Uint8Array(0),
1060
+ new Uint8Array(0),
1061
+ new Uint8Array(0),
1062
+ new Uint8Array(0),
1063
+ new Uint8Array(0),
1064
+ new Uint8Array(0),
1065
+ new Uint8Array(0),
1066
+ new Uint8Array(0),
1067
+ new Uint8Array(0),
1068
+ new Uint8Array(0),
1069
+ new Uint8Array(0),
1070
+ new Uint8Array(0),
1071
+ new Uint8Array(0),
1072
+ new Uint8Array(0),
1073
+ new Uint8Array(0),
1074
+ new Uint8Array(0),
1075
+ new Uint8Array(0),
1076
+ new Uint8Array(0),
1077
+ new Uint8Array(0),
1078
+ new Uint8Array(0),
1079
+ new Uint8Array(0),
1080
+ new Uint8Array(0),
1081
+ new Uint8Array(0),
1082
+ new Uint8Array(0),
1083
+ new Uint8Array(0),
1084
+ new Uint8Array(0),
1085
+ new Uint8Array(0),
1086
+ new Uint8Array(0),
1087
+ new Uint8Array(0),
1088
+ new Uint8Array(0),
1089
+ new Uint8Array(0),
1090
+ new Uint8Array(0),
1091
+ new Uint8Array(0),
1092
+ new Uint8Array(0),
1093
+ new Uint8Array(0),
1094
+ new Uint8Array(0),
1095
+ new Uint8Array(0),
1096
+ new Uint8Array(0),
1097
+ new Uint8Array(0),
1098
+ new Uint8Array(0),
1099
+ new Uint8Array(0),
1100
+ new Uint8Array(0),
1101
+ new Uint8Array(0),
1102
+ new Uint8Array(0),
1103
+ new Uint8Array(0),
1104
+ new Uint8Array(0),
1105
+ new Uint8Array(0),
1106
+ new Uint8Array(0),
1107
+ new Uint8Array(0),
1108
+ new Uint8Array(0),
1109
+ new Uint8Array(0),
1110
+ new Uint8Array(0),
1111
+ new Uint8Array(0),
1112
+ new Uint8Array(0),
1113
+ new Uint8Array(0),
1114
+ new Uint8Array(0),
1115
+ new Uint8Array(0),
1116
+ new Uint8Array(0),
1117
+ new Uint8Array(0),
1118
+ new Uint8Array(0),
1119
+ new Uint8Array(0),
1120
+ new Uint8Array(0),
1121
+ new Uint8Array(0),
1122
+ new Uint8Array(0),
1123
+ new Uint8Array(0),
1124
+ new Uint8Array(0),
1125
+ new Uint8Array(0),
1126
+ new Uint8Array(0),
1127
+ new Uint8Array(0),
1128
+ new Uint8Array(0),
1129
+ new Uint8Array(0),
1130
+ new Uint8Array(0),
1131
+ new Uint8Array(0),
1132
+ new Uint8Array(0),
1133
+ new Uint8Array(0),
1134
+ new Uint8Array(0),
1135
+ new Uint8Array(0),
1136
+ new Uint8Array(0),
1137
+ new Uint8Array(0),
1138
+ new Uint8Array(0),
1139
+ new Uint8Array(0),
1140
+ new Uint8Array(0),
1141
+ new Uint8Array(0),
1142
+ new Uint8Array(0),
1143
+ new Uint8Array(0),
1144
+ new Uint8Array(0),
1145
+ new Uint8Array(0),
1146
+ new Uint8Array(0),
1147
+ new Uint8Array(0),
1148
+ new Uint8Array(0),
1149
+ new Uint8Array(0),
1150
+ ],
1151
+ ),
1152
+ toReplace: $.varRef(init?.toReplace ?? null),
1153
+ }
1154
+ }
1155
+
1156
+ public clone(): byteStringReplacer {
1157
+ const cloned = new byteStringReplacer()
1158
+ cloned._fields = {
1159
+ replacements: $.varRef(this._fields.replacements.value),
1160
+ toReplace: $.varRef(this._fields.toReplace.value),
1161
+ }
1162
+ return cloned
1163
+ }
1164
+
1165
+ public Replace(s: string): string {
1166
+ const r = this
1167
+ let newSize = $.len(s)
1168
+ let anyChanges = false
1169
+ if ($.len(r!.toReplace) * 8 <= $.len(s)) {
1170
+ // The -1 is because we are replacing 1 byte with len(replacements[b]) bytes.
1171
+ for (let _i = 0; _i < $.len(r!.toReplace); _i++) {
1172
+ const x = r!.toReplace![_i]
1173
+ {
1174
+ // The -1 is because we are replacing 1 byte with len(replacements[b]) bytes.
1175
+ {
1176
+ let c = Count(s, x)
1177
+ if (c != 0) {
1178
+ // The -1 is because we are replacing 1 byte with len(replacements[b]) bytes.
1179
+ newSize += c * ($.len(r!.replacements![$.indexString(x, 0)]) - 1)
1180
+ anyChanges = true
1181
+ }
1182
+ }
1183
+ }
1184
+ }
1185
+ } else {
1186
+ // See above for explanation of -1
1187
+ for (let i = 0; i < $.len(s); i++) {
1188
+ let b = $.indexString(s, i)
1189
+
1190
+ // See above for explanation of -1
1191
+ if (r!.replacements![b] != null) {
1192
+ // See above for explanation of -1
1193
+ newSize += $.len(r!.replacements![b]) - 1
1194
+ anyChanges = true
1195
+ }
1196
+ }
1197
+ }
1198
+ if (!anyChanges) {
1199
+ return s
1200
+ }
1201
+ let buf = new Uint8Array(newSize)
1202
+ let j = 0
1203
+ for (let i = 0; i < $.len(s); i++) {
1204
+ let b = $.indexString(s, i)
1205
+ if (r!.replacements![b] != null) {
1206
+ j += copy(buf.subarray(j), r!.replacements![b])
1207
+ } else {
1208
+ buf![j] = b
1209
+ j++
1210
+ }
1211
+ }
1212
+ return $.bytesToString(buf)
1213
+ }
1214
+
1215
+ public WriteString(w: io.Writer, s: string): [number, $.GoError] {
1216
+ const r = this
1217
+ let sw = getStringWriter(w)
1218
+ let last = 0
1219
+ let n: number = 0
1220
+ let err: $.GoError | null = null
1221
+ for (let i = 0; i < $.len(s); i++) {
1222
+ let b = $.indexString(s, i)
1223
+ if (r!.replacements![b] == null) {
1224
+ continue
1225
+ }
1226
+ if (last != i) {
1227
+ let [nw, err] = sw!.WriteString($.sliceString(s, last, i))
1228
+ n += nw
1229
+ if (err != null) {
1230
+ return [n, err]
1231
+ }
1232
+ }
1233
+ last = i + 1
1234
+ let [nw, err] = w!.Write(r!.replacements![b])
1235
+ n += nw
1236
+ if (err != null) {
1237
+ return [n, err]
1238
+ }
1239
+ }
1240
+ if (last != $.len(s)) {
1241
+ let [nw, err] = sw!.WriteString($.sliceString(s, last, undefined))
1242
+ n += nw
1243
+ }
1244
+ return [n, err]
1245
+ }
1246
+
1247
+ // Register this type with the runtime type system
1248
+ static __typeInfo = $.registerStructType(
1249
+ 'byteStringReplacer',
1250
+ new byteStringReplacer(),
1251
+ [
1252
+ {
1253
+ name: 'Replace',
1254
+ args: [{ name: 's', type: { kind: $.TypeKind.Basic, name: 'string' } }],
1255
+ returns: [{ type: { kind: $.TypeKind.Basic, name: 'string' } }],
1256
+ },
1257
+ {
1258
+ name: 'WriteString',
1259
+ args: [
1260
+ { name: 'w', type: 'Writer' },
1261
+ { name: 's', type: { kind: $.TypeKind.Basic, name: 'string' } },
1262
+ ],
1263
+ returns: [
1264
+ { type: { kind: $.TypeKind.Basic, name: 'number' } },
1265
+ {
1266
+ type: {
1267
+ kind: $.TypeKind.Interface,
1268
+ name: 'GoError',
1269
+ methods: [
1270
+ {
1271
+ name: 'Error',
1272
+ args: [],
1273
+ returns: [
1274
+ { type: { kind: $.TypeKind.Basic, name: 'string' } },
1275
+ ],
1276
+ },
1277
+ ],
1278
+ },
1279
+ },
1280
+ ],
1281
+ },
1282
+ ],
1283
+ byteStringReplacer,
1284
+ {
1285
+ replacements: {
1286
+ kind: $.TypeKind.Array,
1287
+ length: 256,
1288
+ elemType: {
1289
+ kind: $.TypeKind.Slice,
1290
+ elemType: { kind: $.TypeKind.Basic, name: 'number' },
1291
+ },
1292
+ },
1293
+ toReplace: {
1294
+ kind: $.TypeKind.Slice,
1295
+ elemType: { kind: $.TypeKind.Basic, name: 'string' },
1296
+ },
1297
+ },
1298
+ )
1299
+ }
1300
+
1301
+ let countCutOff: number = 8
1302
+
1303
+ // Helper function to copy bytes
1304
+ function copy(dst: Uint8Array, src: Uint8Array): number {
1305
+ const n = Math.min(dst.length, src.length)
1306
+ for (let i = 0; i < n; i++) {
1307
+ dst[i] = src[i]
1308
+ }
1309
+ return n
1310
+ }