gofront 1.8.0 → 1.9.1

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 (178) hide show
  1. package/README.md +3 -3
  2. package/package.json +6 -5
  3. package/src/backend/js/expressions.js +1157 -408
  4. package/src/backend/js/index.js +327 -153
  5. package/src/backend/js/natives.js +383 -0
  6. package/src/backend/js/runtime.js +559 -2552
  7. package/src/backend/js/statements.js +670 -158
  8. package/src/backend/js/stdlib/index.js +45 -93
  9. package/src/backend/js/templ.js +32 -45
  10. package/src/backend/js/type-info.js +298 -19
  11. package/src/backend/shared/fixed-float.js +20 -0
  12. package/src/backend/shared/fmt-types.js +91 -170
  13. package/src/backend/shared/host-unicode.js +36 -0
  14. package/src/backend/wasm/boundary.js +490 -965
  15. package/src/backend/wasm/emit-builtins.js +884 -256
  16. package/src/backend/wasm/emit-exprs.js +185 -77
  17. package/src/backend/wasm/emit-maps.js +17 -367
  18. package/src/backend/wasm/emit-shared.js +4 -1
  19. package/src/backend/wasm/emit-stmts.js +524 -240
  20. package/src/backend/wasm/emit.js +176 -38
  21. package/src/backend/wasm/globals.js +48 -8
  22. package/src/backend/wasm/glue.js +2 -4
  23. package/src/backend/wasm/index.js +44 -530
  24. package/src/backend/wasm/method-expr.js +12 -1
  25. package/src/backend/wasm/module-emitter.js +299 -770
  26. package/src/backend/wasm/monomorph.js +139 -8
  27. package/src/backend/wasm/natives.js +600 -0
  28. package/src/backend/wasm/prescan.js +5 -153
  29. package/src/backend/wasm/prune-funcs.js +89 -0
  30. package/src/backend/wasm/stdlib/index.js +2 -32
  31. package/src/backend/wasm/types.js +97 -20
  32. package/src/backend/wasm/variadic.js +9 -4
  33. package/src/cli/cli-core.js +5 -1
  34. package/src/cli/test-runner.js +115 -342
  35. package/src/compiler.js +113 -130
  36. package/src/lexer/lexer.js +106 -11
  37. package/src/lexer/templ-lexer.js +61 -18
  38. package/src/lexer/tokens.js +1 -0
  39. package/src/link/stdlib.js +355 -132
  40. package/src/link/type-names.js +204 -0
  41. package/src/link/wasm.js +30 -6
  42. package/src/lower/bounds.js +153 -0
  43. package/src/lower/captures.js +92 -33
  44. package/src/lower/embedding.js +62 -5
  45. package/src/lower/errors-as.js +196 -0
  46. package/src/lower/fmt-formatters.js +929 -0
  47. package/src/lower/functions.js +225 -7
  48. package/src/lower/gen-types.js +293 -0
  49. package/src/lower/index.js +14 -2
  50. package/src/lower/json-codecs.js +334 -245
  51. package/src/lower/ownership.js +25 -7
  52. package/src/lower/reachability.js +69 -51
  53. package/src/lower/walk.js +12 -0
  54. package/src/parser/declarations.js +30 -5
  55. package/src/parser/expressions.js +111 -57
  56. package/src/parser/statements.js +108 -0
  57. package/src/parser/templ.js +44 -5
  58. package/src/parser/types.js +12 -0
  59. package/src/resolver.js +1 -2
  60. package/src/typechecker/assignability.js +214 -19
  61. package/src/typechecker/const-fold.js +70 -27
  62. package/src/typechecker/constants.js +156 -8
  63. package/src/typechecker/expressions.js +490 -108
  64. package/src/typechecker/index.js +346 -42
  65. package/src/typechecker/init-order.js +136 -40
  66. package/src/typechecker/operand-text.js +41 -0
  67. package/src/typechecker/resolve.js +490 -65
  68. package/src/typechecker/statements.js +288 -27
  69. package/src/typechecker/stdlib/excluded.js +9 -5
  70. package/src/typechecker/stdlib/index.js +25 -9
  71. package/src/typechecker/termination.js +10 -1
  72. package/src/typechecker/types.js +287 -575
  73. package/stdlib/bytes/buffer.go +479 -0
  74. package/stdlib/bytes/bytes.go +1010 -0
  75. package/stdlib/bytes/reader.go +161 -0
  76. package/stdlib/context/context.go +115 -0
  77. package/stdlib/crypto/rand/rand.go +34 -0
  78. package/stdlib/crypto/sha256/sha256.go +249 -0
  79. package/stdlib/encoding/base64/base64.go +331 -0
  80. package/stdlib/encoding/binary/binary.go +332 -0
  81. package/stdlib/encoding/hex/hex.go +140 -0
  82. package/stdlib/encoding/json/json.go +62 -0
  83. package/stdlib/errors/errors.go +174 -0
  84. package/stdlib/fmt/errors.go +110 -0
  85. package/stdlib/fmt/format.go +732 -0
  86. package/stdlib/fmt/print.go +1232 -0
  87. package/stdlib/gom/gom.go +293 -0
  88. package/stdlib/html/html.go +251 -0
  89. package/stdlib/internal/fmtrt/fmtrt.go +163 -0
  90. package/stdlib/internal/jsonrt/dec.go +171 -38
  91. package/stdlib/internal/jsonrt/enc.go +186 -36
  92. package/stdlib/internal/jsonrt/scanner.go +17 -8
  93. package/stdlib/io/io.go +157 -1
  94. package/stdlib/maps/maps.go +131 -0
  95. package/stdlib/math/bits/bits.go +507 -0
  96. package/stdlib/math/extra.go +16 -14
  97. package/stdlib/math/math.go +439 -0
  98. package/stdlib/math/rand/rand.go +297 -0
  99. package/stdlib/os/os.go +93 -0
  100. package/stdlib/path/filepath/filepath.go +47 -0
  101. package/stdlib/path/path.go +394 -0
  102. package/stdlib/regexp/regexp.go +231 -0
  103. package/stdlib/slices/slices.go +526 -0
  104. package/stdlib/slices/sort.go +209 -0
  105. package/stdlib/slices/zsort_cmp.go +480 -0
  106. package/stdlib/slices/zsort_ordered.go +482 -0
  107. package/stdlib/sort/sort.go +391 -452
  108. package/stdlib/sort/zsort_func.go +480 -0
  109. package/stdlib/sort/zsort_iface.go +480 -0
  110. package/stdlib/strconv/float.go +1699 -0
  111. package/stdlib/strconv/isprint.go +752 -0
  112. package/stdlib/strconv/quote.go +235 -50
  113. package/stdlib/strconv/strconv.go +616 -0
  114. package/stdlib/strings/builder.go +95 -0
  115. package/stdlib/strings/reader.go +163 -0
  116. package/stdlib/strings/replacer.go +102 -0
  117. package/stdlib/strings/strings.go +807 -0
  118. package/stdlib/sync/sync.go +268 -0
  119. package/stdlib/testing/async_js.go +61 -0
  120. package/stdlib/testing/benchmark.go +297 -0
  121. package/stdlib/testing/testing.go +523 -0
  122. package/stdlib/time/duration.go +233 -0
  123. package/stdlib/time/format.go +745 -0
  124. package/stdlib/time/parse.go +790 -0
  125. package/stdlib/time/sleep_js.go +63 -0
  126. package/stdlib/time/time.go +834 -0
  127. package/stdlib/unicode/unicode.go +141 -3
  128. package/stdlib/unicode/utf8/utf8.go +464 -0
  129. package/src/backend/js/fmt-runtime.js +0 -573
  130. package/src/backend/js/stdlib/base64.js +0 -12
  131. package/src/backend/js/stdlib/binary.js +0 -102
  132. package/src/backend/js/stdlib/bits.js +0 -119
  133. package/src/backend/js/stdlib/builder.js +0 -98
  134. package/src/backend/js/stdlib/bytes.js +0 -368
  135. package/src/backend/js/stdlib/errors.js +0 -45
  136. package/src/backend/js/stdlib/fmt.js +0 -517
  137. package/src/backend/js/stdlib/gom.js +0 -155
  138. package/src/backend/js/stdlib/hex.js +0 -17
  139. package/src/backend/js/stdlib/html.js +0 -20
  140. package/src/backend/js/stdlib/io.js +0 -137
  141. package/src/backend/js/stdlib/json.js +0 -1167
  142. package/src/backend/js/stdlib/maps.js +0 -37
  143. package/src/backend/js/stdlib/math.js +0 -85
  144. package/src/backend/js/stdlib/os.js +0 -13
  145. package/src/backend/js/stdlib/path.js +0 -48
  146. package/src/backend/js/stdlib/rand.js +0 -32
  147. package/src/backend/js/stdlib/regexp.js +0 -54
  148. package/src/backend/js/stdlib/sha256.js +0 -12
  149. package/src/backend/js/stdlib/shared.js +0 -17
  150. package/src/backend/js/stdlib/simd.js +0 -34
  151. package/src/backend/js/stdlib/slices.js +0 -107
  152. package/src/backend/js/stdlib/sort.js +0 -30
  153. package/src/backend/js/stdlib/strconv.js +0 -79
  154. package/src/backend/js/stdlib/strings.js +0 -301
  155. package/src/backend/js/stdlib/sync.js +0 -13
  156. package/src/backend/js/stdlib/testing.js +0 -41
  157. package/src/backend/js/stdlib/time.js +0 -152
  158. package/src/backend/js/stdlib/unicode.js +0 -25
  159. package/src/backend/js/stdlib/utf8.js +0 -26
  160. package/src/backend/wasm/stdlib/bytes.js +0 -6716
  161. package/src/backend/wasm/stdlib/core.js +0 -10278
  162. package/src/backend/wasm/stdlib/io.js +0 -3578
  163. package/src/backend/wasm/stdlib/packages.js +0 -2402
  164. package/src/backend/wasm/stdlib/pure.js +0 -720
  165. package/src/backend/wasm/stdlib/time.js +0 -2229
  166. package/src/typechecker/stdlib/core.js +0 -1079
  167. package/src/typechecker/stdlib/extended.js +0 -1210
  168. package/stdlib/bytes/iter.go +0 -192
  169. package/stdlib/bytes/search.go +0 -240
  170. package/stdlib/bytes/split.go +0 -218
  171. package/stdlib/errors/overlay.go +0 -12
  172. package/stdlib/maps/iter.go +0 -65
  173. package/stdlib/slices/extra.go +0 -73
  174. package/stdlib/slices/iter.go +0 -113
  175. package/stdlib/strings/extra.go +0 -35
  176. package/stdlib/strings/iter.go +0 -122
  177. package/stdlib/sync/extra.go +0 -105
  178. package/stdlib/unicode/utf8/bytes.go +0 -239
@@ -0,0 +1,1010 @@
1
+ //go:build gofront
2
+
3
+ //gofront:target both
4
+
5
+ // Package bytes implements functions for the manipulation of byte slices,
6
+ // written in Go over the real package's algorithms. Offsets are byte
7
+ // offsets and UTF-8 is decoded as Go does, so an invalid sequence reads as
8
+ // (RuneError, 1). Like Go's, the slices that the split and sequence
9
+ // functions return alias the input and have their capacity clipped.
10
+ package bytes
11
+
12
+ import (
13
+ "iter"
14
+ "unicode"
15
+ )
16
+
17
+ const (
18
+ runeError = 0xFFFD
19
+ runeSelf = 0x80
20
+ )
21
+
22
+ // decodeRune unpacks the first UTF-8 encoding in p and returns the rune and
23
+ // its width in bytes, as utf8.DecodeRune does: an invalid or incomplete
24
+ // encoding is (RuneError, 1) and p must not be empty.
25
+ func decodeRune(p []byte) (rune, int) {
26
+ b0 := int(p[0])
27
+ if b0 < runeSelf {
28
+ return rune(b0), 1
29
+ }
30
+ n, lo, mask := 0, 0, 0
31
+ if b0 >= 0xC2 && b0 <= 0xDF {
32
+ n, lo, mask = 2, 0x80, 0x1F
33
+ } else if b0 >= 0xE0 && b0 <= 0xEF {
34
+ n, lo, mask = 3, 0x800, 0x0F
35
+ } else if b0 >= 0xF0 && b0 <= 0xF4 {
36
+ n, lo, mask = 4, 0x10000, 0x07
37
+ } else {
38
+ return runeError, 1
39
+ }
40
+ if len(p) < n {
41
+ return runeError, 1
42
+ }
43
+ r := b0 & mask
44
+ for i := 1; i < n; i++ {
45
+ b := int(p[i])
46
+ if b&0xC0 != 0x80 {
47
+ return runeError, 1
48
+ }
49
+ r = r<<6 | b&0x3F
50
+ }
51
+ if r < lo || r > 0x10FFFF || (r >= 0xD800 && r <= 0xDFFF) {
52
+ return runeError, 1
53
+ }
54
+ return rune(r), n
55
+ }
56
+
57
+ // isSpace is unicode.IsSpace as a func(rune) bool.
58
+ func isSpace(r rune) bool {
59
+ return unicode.IsSpace(r)
60
+ }
61
+
62
+ // Lines returns an iterator over the newline-terminated lines in the byte slice s.
63
+ // The lines yielded by the iterator include their terminating newlines.
64
+ // If s is empty, the iterator yields no lines at all.
65
+ // If s does not end in a newline, the final yielded line will not end in a newline.
66
+ // The iterator yields slices of the original slice s.
67
+ func Lines(s []byte) iter.Seq[[]byte] {
68
+ return func(yield func([]byte) bool) {
69
+ for len(s) > 0 {
70
+ var line []byte
71
+ if i := IndexByte(s, '\n'); i >= 0 {
72
+ line, s = s[:i+1:i+1], s[i+1:]
73
+ } else {
74
+ line, s = s[:len(s):len(s)], nil
75
+ }
76
+ if !yield(line) {
77
+ return
78
+ }
79
+ }
80
+ }
81
+ }
82
+
83
+ // explodeSeq returns an iterator over the UTF-8 encodings of the runes in s.
84
+ func explodeSeq(s []byte) iter.Seq[[]byte] {
85
+ return func(yield func([]byte) bool) {
86
+ for len(s) > 0 {
87
+ _, size := decodeRune(s)
88
+ if !yield(s[:size:size]) {
89
+ return
90
+ }
91
+ s = s[size:]
92
+ }
93
+ }
94
+ }
95
+
96
+ // splitSeq is SplitSeq or SplitAfterSeq, configured by how many
97
+ // bytes of sep to include in the results (none or all).
98
+ func splitSeq(s, sep []byte, sepSave int) iter.Seq[[]byte] {
99
+ if len(sep) == 0 {
100
+ return explodeSeq(s)
101
+ }
102
+ return func(yield func([]byte) bool) {
103
+ for {
104
+ i := Index(s, sep)
105
+ if i < 0 {
106
+ break
107
+ }
108
+ frag := s[:i+sepSave]
109
+ if !yield(frag[:len(frag):len(frag)]) {
110
+ return
111
+ }
112
+ s = s[i+len(sep):]
113
+ }
114
+ yield(s[:len(s):len(s)])
115
+ }
116
+ }
117
+
118
+ // SplitSeq returns an iterator over subslices of s split around sep.
119
+ // The iterator yields the same subslices that would be returned by Split(s, sep),
120
+ // but without constructing the slice.
121
+ // It returns a single-use iterator.
122
+ func SplitSeq(s, sep []byte) iter.Seq[[]byte] {
123
+ return splitSeq(s, sep, 0)
124
+ }
125
+
126
+ // SplitAfterSeq returns an iterator over subslices of s split after each instance of sep.
127
+ // The iterator yields the same subslices that would be returned by SplitAfter(s, sep),
128
+ // but without constructing the slice.
129
+ // It returns a single-use iterator.
130
+ func SplitAfterSeq(s, sep []byte) iter.Seq[[]byte] {
131
+ return splitSeq(s, sep, len(sep))
132
+ }
133
+
134
+ // FieldsSeq returns an iterator over subslices of s split around runs of
135
+ // whitespace characters, as defined by unicode.IsSpace.
136
+ // The iterator yields the same subslices that would be returned by Fields(s),
137
+ // but without constructing the slice.
138
+ func FieldsSeq(s []byte) iter.Seq[[]byte] {
139
+ return FieldsFuncSeq(s, isSpace)
140
+ }
141
+
142
+ // FieldsFuncSeq returns an iterator over subslices of s split around runs of
143
+ // Unicode code points satisfying f(c).
144
+ // The iterator yields the same subslices that would be returned by FieldsFunc(s),
145
+ // but without constructing the slice.
146
+ func FieldsFuncSeq(s []byte, f func(rune) bool) iter.Seq[[]byte] {
147
+ return func(yield func([]byte) bool) {
148
+ start := -1
149
+ for i := 0; i < len(s); {
150
+ size := 1
151
+ r := rune(s[i])
152
+ if r >= runeSelf {
153
+ r, size = decodeRune(s[i:])
154
+ }
155
+ if f(r) {
156
+ if start >= 0 {
157
+ if !yield(s[start:i:i]) {
158
+ return
159
+ }
160
+ start = -1
161
+ }
162
+ } else if start < 0 {
163
+ start = i
164
+ }
165
+ i += size
166
+ }
167
+ if start >= 0 {
168
+ yield(s[start:len(s):len(s)])
169
+ }
170
+ }
171
+ }
172
+
173
+
174
+ // IndexByte returns the index of the first instance of c in b, or -1 if c is
175
+ // not present in b.
176
+ //
177
+ //gofront:native bytes.IndexByte
178
+ func IndexByte(b []byte, c byte) int {
179
+ for i, x := range b {
180
+ if x == c {
181
+ return i
182
+ }
183
+ }
184
+ return -1
185
+ }
186
+
187
+ // Equal reports whether a and b are the same length and contain the same
188
+ // bytes. A nil argument is equivalent to an empty slice.
189
+ //
190
+ //gofront:native bytes.Equal
191
+ func Equal(a, b []byte) bool {
192
+ if len(a) != len(b) {
193
+ return false
194
+ }
195
+ for i := range a {
196
+ if a[i] != b[i] {
197
+ return false
198
+ }
199
+ }
200
+ return true
201
+ }
202
+
203
+ // Index returns the index of the first instance of sep in s, or -1 if sep is
204
+ // not present in s.
205
+ func Index(s, sep []byte) int {
206
+ n := len(sep)
207
+ switch {
208
+ case n == 0:
209
+ return 0
210
+ case n == 1:
211
+ return IndexByte(s, sep[0])
212
+ case n == len(s):
213
+ if Equal(sep, s) {
214
+ return 0
215
+ }
216
+ return -1
217
+ case n > len(s):
218
+ return -1
219
+ }
220
+ c0 := sep[0]
221
+ for i := 0; i+n <= len(s); i++ {
222
+ j := IndexByte(s[i:len(s)-n+1], c0)
223
+ if j < 0 {
224
+ return -1
225
+ }
226
+ i += j
227
+ if Equal(s[i:i+n], sep) {
228
+ return i
229
+ }
230
+ }
231
+ return -1
232
+ }
233
+
234
+ // LastIndex returns the index of the last instance of sep in s, or -1 if sep
235
+ // is not present in s.
236
+ func LastIndex(s, sep []byte) int {
237
+ n := len(sep)
238
+ if n == 0 {
239
+ return len(s)
240
+ }
241
+ for i := len(s) - n; i >= 0; i-- {
242
+ if s[i] == sep[0] && Equal(s[i:i+n], sep) {
243
+ return i
244
+ }
245
+ }
246
+ return -1
247
+ }
248
+
249
+ // LastIndexByte returns the index of the last instance of c in s, or -1 if c
250
+ // is not present in s.
251
+ func LastIndexByte(s []byte, c byte) int {
252
+ for i := len(s) - 1; i >= 0; i-- {
253
+ if s[i] == c {
254
+ return i
255
+ }
256
+ }
257
+ return -1
258
+ }
259
+
260
+ // Contains reports whether subslice is within b.
261
+ func Contains(b, subslice []byte) bool {
262
+ return Index(b, subslice) != -1
263
+ }
264
+
265
+ // ContainsAny reports whether any of the UTF-8-encoded code points in chars
266
+ // are within b.
267
+ func ContainsAny(b []byte, chars string) bool {
268
+ return IndexAny(b, chars) >= 0
269
+ }
270
+
271
+ // ContainsRune reports whether the rune is contained in the UTF-8-encoded
272
+ // byte slice b.
273
+ func ContainsRune(b []byte, r rune) bool {
274
+ return IndexRune(b, r) >= 0
275
+ }
276
+
277
+ // Count counts the number of non-overlapping instances of sep in s.
278
+ // If sep is an empty slice, Count returns 1 + the number of UTF-8-encoded
279
+ // code points in s.
280
+ func Count(s, sep []byte) int {
281
+ if len(sep) == 0 {
282
+ return runeCount(s) + 1
283
+ }
284
+ return countSep(s, sep)
285
+ }
286
+
287
+ // HasPrefix reports whether the byte slice s begins with prefix.
288
+ func HasPrefix(s, prefix []byte) bool {
289
+ return len(s) >= len(prefix) && Equal(s[:len(prefix)], prefix)
290
+ }
291
+
292
+ // HasSuffix reports whether the byte slice s ends with suffix.
293
+ func HasSuffix(s, suffix []byte) bool {
294
+ return len(s) >= len(suffix) && Equal(s[len(s)-len(suffix):], suffix)
295
+ }
296
+
297
+ // Clone returns a copy of b[:len(b)].
298
+ // The result may have additional unused capacity.
299
+ // Clone(nil) returns nil.
300
+ func Clone(b []byte) []byte {
301
+ if b == nil {
302
+ return nil
303
+ }
304
+ return append([]byte{}, b...)
305
+ }
306
+
307
+ // Cut slices s around the first instance of sep,
308
+ // returning the text before and after sep.
309
+ // The found result reports whether sep appears in s.
310
+ // If sep does not appear in s, cut returns s, nil, false.
311
+ func Cut(s, sep []byte) (before, after []byte, found bool) {
312
+ if i := Index(s, sep); i >= 0 {
313
+ return s[:i], s[i+len(sep):], true
314
+ }
315
+ return s, nil, false
316
+ }
317
+
318
+ // Repeat returns a new byte slice consisting of count copies of b.
319
+ // It panics if count is negative.
320
+ func Repeat(b []byte, count int) []byte {
321
+ if count < 0 {
322
+ panic("bytes: negative Repeat count")
323
+ }
324
+ nb := make([]byte, 0, len(b)*count)
325
+ for i := 0; i < count; i++ {
326
+ nb = append(nb, b...)
327
+ }
328
+ return nb
329
+ }
330
+
331
+ // Split slices s into all subslices separated by sep and returns a slice of
332
+ // the subslices between those separators.
333
+ // If sep is empty, Split splits after each UTF-8 sequence.
334
+ // It is equivalent to SplitN with a count of -1.
335
+ func Split(s, sep []byte) [][]byte { return genSplit(s, sep, 0, -1) }
336
+
337
+ // SplitN slices s into subslices separated by sep and returns a slice of
338
+ // the subslices between those separators.
339
+ // The count determines the number of subslices to return:
340
+ // - n > 0: at most n subslices; the last subslice will be the unsplit remainder;
341
+ // - n == 0: the result is nil (zero subslices);
342
+ // - n < 0: all subslices.
343
+ func SplitN(s, sep []byte, n int) [][]byte { return genSplit(s, sep, 0, n) }
344
+
345
+ // Join concatenates the elements of s to create a new byte slice. The separator
346
+ // sep is placed between elements in the resulting slice.
347
+ func Join(s [][]byte, sep []byte) []byte {
348
+ if len(s) == 0 {
349
+ return []byte{}
350
+ }
351
+ if len(s) == 1 {
352
+ return append([]byte(nil), s[0]...)
353
+ }
354
+ n := len(sep) * (len(s) - 1)
355
+ for _, v := range s {
356
+ n += len(v)
357
+ }
358
+ b := make([]byte, 0, n)
359
+ b = append(b, s[0]...)
360
+ for _, v := range s[1:] {
361
+ b = append(b, sep...)
362
+ b = append(b, v...)
363
+ }
364
+ return b
365
+ }
366
+
367
+ // span is the byte range of one field.
368
+ type span struct {
369
+ start int
370
+ end int
371
+ }
372
+
373
+ // FieldsFunc interprets s as a sequence of UTF-8-encoded code points.
374
+ // It splits the slice s at each run of code points c satisfying f(c) and
375
+ // returns a slice of subslices of s. If all code points in s satisfy f(c), or
376
+ // len(s) == 0, an empty slice is returned.
377
+ func FieldsFunc(s []byte, f func(rune) bool) [][]byte {
378
+ spans := make([]span, 0, 32)
379
+ start := -1
380
+ for i := 0; i < len(s); {
381
+ size := 1
382
+ r := rune(s[i])
383
+ if r >= runeSelf {
384
+ r, size = decodeRune(s[i:])
385
+ }
386
+ if f(r) {
387
+ if start >= 0 {
388
+ spans = append(spans, span{start, i})
389
+ start = -1
390
+ }
391
+ } else if start < 0 {
392
+ start = i
393
+ }
394
+ i += size
395
+ }
396
+ if start >= 0 {
397
+ spans = append(spans, span{start, len(s)})
398
+ }
399
+ a := make([][]byte, len(spans))
400
+ for i, sp := range spans {
401
+ a[i] = s[sp.start:sp.end:sp.end]
402
+ }
403
+ return a
404
+ }
405
+
406
+ // Fields interprets s as a sequence of UTF-8-encoded code points.
407
+ // It splits the slice s around each instance of one or more consecutive white
408
+ // space characters, as defined by unicode.IsSpace, returning a slice of
409
+ // subslices of s or an empty slice if s contains only white space.
410
+ func Fields(s []byte) [][]byte { return FieldsFunc(s, isSpace) }
411
+
412
+ // Map returns a copy of the byte slice s with all its characters modified
413
+ // according to the mapping function. If mapping returns a negative value, the
414
+ // character is dropped from the byte slice with no replacement. The characters
415
+ // in s and the output are interpreted as UTF-8-encoded code points.
416
+ func Map(mapping func(r rune) rune, s []byte) []byte {
417
+ b := make([]byte, 0, len(s))
418
+ for i := 0; i < len(s); {
419
+ wid := 1
420
+ r := rune(s[i])
421
+ if r >= runeSelf {
422
+ r, wid = decodeRune(s[i:])
423
+ }
424
+ r = mapping(r)
425
+ if r >= 0 {
426
+ b = appendRune(b, r)
427
+ }
428
+ i += wid
429
+ }
430
+ return b
431
+ }
432
+
433
+ func upperRune(r rune) rune { return unicode.ToUpper(r) }
434
+ func lowerRune(r rune) rune { return unicode.ToLower(r) }
435
+
436
+ // ToUpper returns a copy of s with all Unicode letters mapped to their
437
+ // upper case.
438
+ func ToUpper(s []byte) []byte { return Map(upperRune, s) }
439
+
440
+ // ToLower returns a copy of s with all Unicode letters mapped to their
441
+ // lower case.
442
+ func ToLower(s []byte) []byte { return Map(lowerRune, s) }
443
+
444
+ // ToTitle treats s as UTF-8-encoded bytes and returns a copy with all the
445
+ // Unicode letters mapped to their title case.
446
+ func ToTitle(s []byte) []byte { return Map(unicode.ToTitle, s) }
447
+
448
+ // ToValidUTF8 treats s as UTF-8-encoded bytes and returns a copy with each
449
+ // run of bytes representing invalid UTF-8 replaced with the bytes in
450
+ // replacement, which may be empty.
451
+ func ToValidUTF8(s, replacement []byte) []byte {
452
+ b := make([]byte, 0, len(s)+len(replacement))
453
+ invalid := false
454
+ for i := 0; i < len(s); {
455
+ c := s[i]
456
+ if c < runeSelf {
457
+ i++
458
+ invalid = false
459
+ b = append(b, c)
460
+ continue
461
+ }
462
+ _, wid := decodeRune(s[i:])
463
+ if wid == 1 {
464
+ i++
465
+ if !invalid {
466
+ invalid = true
467
+ b = append(b, replacement...)
468
+ }
469
+ continue
470
+ }
471
+ invalid = false
472
+ b = append(b, s[i:i+wid]...)
473
+ i += wid
474
+ }
475
+ return b
476
+ }
477
+
478
+ // Replace returns a copy of the slice s with the first n
479
+ // non-overlapping instances of old replaced by new.
480
+ // If old is empty, it matches at the beginning of the slice
481
+ // and after each UTF-8 sequence, yielding up to k+1 replacements
482
+ // for a k-rune slice.
483
+ // If n < 0, there is no limit on the number of replacements.
484
+ func Replace(s, old, new []byte, n int) []byte {
485
+ m := 0
486
+ if n != 0 {
487
+ m = Count(s, old)
488
+ }
489
+ if m == 0 {
490
+ return append([]byte(nil), s...)
491
+ }
492
+ if n < 0 || m < n {
493
+ n = m
494
+ }
495
+ t := make([]byte, 0, len(s)+n*(len(new)-len(old)))
496
+ start := 0
497
+ for i := 0; i < n; i++ {
498
+ j := start
499
+ if len(old) == 0 {
500
+ if i > 0 {
501
+ _, wid := decodeRune(s[start:])
502
+ j += wid
503
+ }
504
+ } else {
505
+ j += Index(s[start:], old)
506
+ }
507
+ t = append(t, s[start:j]...)
508
+ t = append(t, new...)
509
+ start = j + len(old)
510
+ }
511
+ t = append(t, s[start:]...)
512
+ return t
513
+ }
514
+
515
+ // ReplaceAll returns a copy of the slice s with all
516
+ // non-overlapping instances of old replaced by new.
517
+ // If old is empty, it matches at the beginning of the slice
518
+ // and after each UTF-8 sequence, yielding up to k+1 replacements
519
+ // for a k-rune slice.
520
+ func ReplaceAll(s, old, new []byte) []byte {
521
+ return Replace(s, old, new, -1)
522
+ }
523
+
524
+ // TrimFunc returns a subslice of s by slicing off all leading and trailing
525
+ // UTF-8-encoded code points c that satisfy f(c).
526
+ func TrimFunc(s []byte, f func(r rune) bool) []byte {
527
+ return TrimRightFunc(TrimLeftFunc(s, f), f)
528
+ }
529
+
530
+ // Trim returns a subslice of s by slicing off all leading and
531
+ // trailing UTF-8-encoded code points contained in cutset.
532
+ func Trim(s []byte, cutset string) []byte {
533
+ if len(s) == 0 {
534
+ return nil
535
+ }
536
+ if cutset == "" {
537
+ return s
538
+ }
539
+ in := func(r rune) bool { return containsRuneIn(cutset, r) }
540
+ return TrimLeftFunc(TrimRightFunc(s, in), in)
541
+ }
542
+
543
+ // TrimLeft returns a subslice of s by slicing off all leading
544
+ // UTF-8-encoded code points contained in cutset.
545
+ func TrimLeft(s []byte, cutset string) []byte {
546
+ if len(s) == 0 {
547
+ return nil
548
+ }
549
+ if cutset == "" {
550
+ return s
551
+ }
552
+ return TrimLeftFunc(s, func(r rune) bool { return containsRuneIn(cutset, r) })
553
+ }
554
+
555
+ // TrimRight returns a subslice of s by slicing off all trailing
556
+ // UTF-8-encoded code points that are contained in cutset.
557
+ func TrimRight(s []byte, cutset string) []byte {
558
+ if len(s) == 0 || cutset == "" {
559
+ return s
560
+ }
561
+ return TrimRightFunc(s, func(r rune) bool { return containsRuneIn(cutset, r) })
562
+ }
563
+
564
+ // TrimSpace returns a subslice of s by slicing off all leading and
565
+ // trailing white space, as defined by Unicode.
566
+ func TrimSpace(s []byte) []byte { return TrimFunc(s, isSpace) }
567
+
568
+ // TrimPrefix returns s without the provided leading prefix string.
569
+ // If s doesn't start with prefix, s is returned unchanged.
570
+ func TrimPrefix(s, prefix []byte) []byte {
571
+ if HasPrefix(s, prefix) {
572
+ return s[len(prefix):]
573
+ }
574
+ return s
575
+ }
576
+
577
+ // TrimSuffix returns s without the provided trailing suffix string.
578
+ // If s doesn't end with suffix, s is returned unchanged.
579
+ func TrimSuffix(s, suffix []byte) []byte {
580
+ if HasSuffix(s, suffix) {
581
+ return s[:len(s)-len(suffix)]
582
+ }
583
+ return s
584
+ }
585
+
586
+ // Compare returns an integer comparing two byte slices lexicographically.
587
+ // The result will be 0 if a == b, -1 if a < b, and +1 if a > b.
588
+ // A nil argument is equivalent to an empty slice.
589
+ //
590
+ //gofront:native bytes.Compare
591
+ func Compare(a, b []byte) int {
592
+ n := len(a)
593
+ if len(b) < n {
594
+ n = len(b)
595
+ }
596
+ for i := 0; i < n; i++ {
597
+ if a[i] != b[i] {
598
+ if a[i] < b[i] {
599
+ return -1
600
+ }
601
+ return 1
602
+ }
603
+ }
604
+ if len(a) < len(b) {
605
+ return -1
606
+ }
607
+ if len(a) > len(b) {
608
+ return 1
609
+ }
610
+ return 0
611
+ }
612
+
613
+ // decodeLastRune unpacks the last UTF-8 encoding in p and returns the rune and
614
+ // its width in bytes, as utf8.DecodeLastRune does: an invalid or incomplete
615
+ // encoding is (RuneError, 1) and p must not be empty.
616
+ func decodeLastRune(p []byte) (rune, int) {
617
+ end := len(p)
618
+ r := rune(p[end-1])
619
+ if r < runeSelf {
620
+ return r, 1
621
+ }
622
+ start := end - 1
623
+ lim := end - 4
624
+ if lim < 0 {
625
+ lim = 0
626
+ }
627
+ for start--; start >= lim; start-- {
628
+ if p[start]&0xC0 != 0x80 {
629
+ break
630
+ }
631
+ }
632
+ if start < 0 {
633
+ start = 0
634
+ }
635
+ r, size := decodeRune(p[start:end])
636
+ if start+size != end {
637
+ return runeError, 1
638
+ }
639
+ return r, size
640
+ }
641
+
642
+ // EqualFold reports whether s and t, interpreted as UTF-8 strings,
643
+ // are equal under simple Unicode case-folding, which is a more general
644
+ // form of case-insensitivity.
645
+ func EqualFold(s, t []byte) bool {
646
+ for len(s) != 0 && len(t) != 0 {
647
+ var sr, tr rune
648
+ if s[0] < runeSelf {
649
+ sr, s = rune(s[0]), s[1:]
650
+ } else {
651
+ r, size := decodeRune(s)
652
+ sr, s = r, s[size:]
653
+ }
654
+ if t[0] < runeSelf {
655
+ tr, t = rune(t[0]), t[1:]
656
+ } else {
657
+ r, size := decodeRune(t)
658
+ tr, t = r, t[size:]
659
+ }
660
+ if tr == sr {
661
+ continue
662
+ }
663
+ if tr < sr {
664
+ tr, sr = sr, tr
665
+ }
666
+ if tr < runeSelf {
667
+ if 'A' <= sr && sr <= 'Z' && tr == sr+'a'-'A' {
668
+ continue
669
+ }
670
+ return false
671
+ }
672
+ r := unicode.SimpleFold(sr)
673
+ for r != sr && r < tr {
674
+ r = unicode.SimpleFold(r)
675
+ }
676
+ if r == tr {
677
+ continue
678
+ }
679
+ return false
680
+ }
681
+ return len(s) == len(t)
682
+ }
683
+
684
+ // IndexRune interprets s as a sequence of UTF-8-encoded code points.
685
+ // It returns the byte index of the first occurrence in s of the given rune.
686
+ // It returns -1 if rune is not present in s.
687
+ // If r is utf8.RuneError, it returns the first instance of any
688
+ // invalid UTF-8 byte sequence.
689
+ func IndexRune(s []byte, r rune) int {
690
+ if r < 0 || r > 0x10FFFF || (r >= 0xD800 && r <= 0xDFFF) {
691
+ return -1
692
+ }
693
+ if r < runeSelf {
694
+ return IndexByte(s, byte(r))
695
+ }
696
+ for i := 0; i < len(s); {
697
+ c, size := decodeRune(s[i:])
698
+ if c == r {
699
+ return i
700
+ }
701
+ i += size
702
+ }
703
+ return -1
704
+ }
705
+
706
+ // containsRuneIn reports whether chars contains r, treating an invalid sequence
707
+ // in chars as utf8.RuneError.
708
+ func containsRuneIn(chars string, r rune) bool {
709
+ for _, c := range chars {
710
+ if c == r {
711
+ return true
712
+ }
713
+ }
714
+ return false
715
+ }
716
+
717
+ // IndexAny interprets s as a sequence of UTF-8-encoded Unicode code points.
718
+ // It returns the byte index of the first occurrence in s of any of the Unicode
719
+ // code points in chars. It returns -1 if chars is empty or if there is no code
720
+ // point in common.
721
+ func IndexAny(s []byte, chars string) int {
722
+ if len(chars) == 0 {
723
+ return -1
724
+ }
725
+ for i := 0; i < len(s); {
726
+ r, size := decodeRune(s[i:])
727
+ if containsRuneIn(chars, r) {
728
+ return i
729
+ }
730
+ i += size
731
+ }
732
+ return -1
733
+ }
734
+
735
+ // LastIndexAny interprets s as a sequence of UTF-8-encoded Unicode code
736
+ // points. It returns the byte index of the last occurrence in s of any of
737
+ // the Unicode code points in chars. It returns -1 if chars is empty or if
738
+ // there is no code point in common.
739
+ func LastIndexAny(s []byte, chars string) int {
740
+ if len(chars) == 0 {
741
+ return -1
742
+ }
743
+ for i := len(s); i > 0; {
744
+ r, size := decodeLastRune(s[:i])
745
+ i -= size
746
+ if containsRuneIn(chars, r) {
747
+ return i
748
+ }
749
+ }
750
+ return -1
751
+ }
752
+
753
+ func indexFunc(s []byte, f func(rune) bool, truth bool) int {
754
+ for i := 0; i < len(s); {
755
+ r, size := decodeRune(s[i:])
756
+ if f(r) == truth {
757
+ return i
758
+ }
759
+ i += size
760
+ }
761
+ return -1
762
+ }
763
+
764
+ func lastIndexFunc(s []byte, f func(rune) bool, truth bool) int {
765
+ for i := len(s); i > 0; {
766
+ r, size := decodeLastRune(s[:i])
767
+ i -= size
768
+ if f(r) == truth {
769
+ return i
770
+ }
771
+ }
772
+ return -1
773
+ }
774
+
775
+ // IndexFunc interprets s as a sequence of UTF-8-encoded code points.
776
+ // It returns the byte index in s of the first Unicode
777
+ // code point satisfying f(c), or -1 if none do.
778
+ func IndexFunc(s []byte, f func(r rune) bool) int {
779
+ return indexFunc(s, f, true)
780
+ }
781
+
782
+ // LastIndexFunc interprets s as a sequence of UTF-8-encoded code points.
783
+ // It returns the byte index in s of the last Unicode
784
+ // code point satisfying f(c), or -1 if none do.
785
+ func LastIndexFunc(s []byte, f func(r rune) bool) int {
786
+ return lastIndexFunc(s, f, true)
787
+ }
788
+
789
+ // ContainsFunc reports whether any of the UTF-8-encoded code points
790
+ // in b satisfy f(c).
791
+ func ContainsFunc(b []byte, f func(rune) bool) bool {
792
+ return indexFunc(b, f, true) >= 0
793
+ }
794
+
795
+ // CutPrefix returns s without the provided leading prefix byte slice
796
+ // and reports whether it found the prefix.
797
+ // If s doesn't start with prefix, CutPrefix returns s, false.
798
+ // If prefix is the empty byte slice, CutPrefix returns s, true.
799
+ func CutPrefix(s, prefix []byte) (after []byte, found bool) {
800
+ if len(s) < len(prefix) || Compare(s[:len(prefix)], prefix) != 0 {
801
+ return s, false
802
+ }
803
+ return s[len(prefix):], true
804
+ }
805
+
806
+ // CutSuffix returns s without the provided ending suffix byte slice
807
+ // and reports whether it found the suffix.
808
+ // If s doesn't end with suffix, CutSuffix returns s, false.
809
+ // If suffix is the empty byte slice, CutSuffix returns s, true.
810
+ func CutSuffix(s, suffix []byte) (before []byte, found bool) {
811
+ if len(s) < len(suffix) || Compare(s[len(s)-len(suffix):], suffix) != 0 {
812
+ return s, false
813
+ }
814
+ return s[:len(s)-len(suffix)], true
815
+ }
816
+
817
+ // runeCount returns the number of runes in p, counting each invalid byte as
818
+ // one rune as utf8.RuneCount does.
819
+ func runeCount(p []byte) int {
820
+ n := 0
821
+ for i := 0; i < len(p); n++ {
822
+ _, size := decodeRune(p[i:])
823
+ i += size
824
+ }
825
+ return n
826
+ }
827
+
828
+ // countSep counts the non-overlapping instances of sep in s; sep must not be
829
+ // empty.
830
+ func countSep(s, sep []byte) int {
831
+ n := 0
832
+ for {
833
+ i := Index(s, sep)
834
+ if i < 0 {
835
+ return n
836
+ }
837
+ n++
838
+ s = s[i+len(sep):]
839
+ }
840
+ }
841
+
842
+ // explode splits s into a slice of UTF-8 sequences, one per Unicode code point
843
+ // (still slices of bytes), up to a maximum of n byte slices. Invalid UTF-8
844
+ // sequences are chopped into individual bytes.
845
+ func explode(s []byte, n int) [][]byte {
846
+ l := runeCount(s)
847
+ if n < 0 || n > l {
848
+ n = l
849
+ }
850
+ a := make([][]byte, n)
851
+ for i := 0; i < n-1; i++ {
852
+ _, size := decodeRune(s)
853
+ a[i] = s[:size:size]
854
+ s = s[size:]
855
+ }
856
+ if n > 0 {
857
+ a[n-1] = s[:len(s):len(s)]
858
+ }
859
+ return a
860
+ }
861
+
862
+ // genSplit splits s around sep, including sepSave bytes of sep in each
863
+ // subslice, into at most n subslices.
864
+ func genSplit(s, sep []byte, sepSave, n int) [][]byte {
865
+ if n == 0 {
866
+ return nil
867
+ }
868
+ if len(sep) == 0 {
869
+ return explode(s, n)
870
+ }
871
+ if n < 0 {
872
+ n = countSep(s, sep) + 1
873
+ }
874
+ if n > len(s)+1 {
875
+ n = len(s) + 1
876
+ }
877
+ a := make([][]byte, n)
878
+ n--
879
+ i := 0
880
+ for i < n {
881
+ m := Index(s, sep)
882
+ if m < 0 {
883
+ break
884
+ }
885
+ a[i] = s[: m+sepSave : m+sepSave]
886
+ s = s[m+len(sep):]
887
+ i++
888
+ }
889
+ a[i] = s[:len(s):len(s)]
890
+ return a[:i+1]
891
+ }
892
+
893
+ // SplitAfter slices s into all subslices after each instance of sep and
894
+ // returns a slice of those subslices.
895
+ // If sep is empty, SplitAfter splits after each UTF-8 sequence.
896
+ // It is equivalent to SplitAfterN with a count of -1.
897
+ func SplitAfter(s, sep []byte) [][]byte {
898
+ return genSplit(s, sep, len(sep), -1)
899
+ }
900
+
901
+ // SplitAfterN slices s into subslices after each instance of sep and
902
+ // returns a slice of those subslices.
903
+ // The count determines the number of subslices to return:
904
+ // - n > 0: at most n subslices; the last subslice will be the unsplit remainder;
905
+ // - n == 0: the result is nil (zero subslices);
906
+ // - n < 0: all subslices.
907
+ func SplitAfterN(s, sep []byte, n int) [][]byte {
908
+ return genSplit(s, sep, len(sep), n)
909
+ }
910
+
911
+ // Runes interprets s as a sequence of UTF-8-encoded code points.
912
+ // It returns a slice of runes (Unicode code points) equivalent to s.
913
+ func Runes(s []byte) []rune {
914
+ t := make([]rune, runeCount(s))
915
+ i := 0
916
+ for len(s) > 0 {
917
+ r, l := decodeRune(s)
918
+ t[i] = r
919
+ i++
920
+ s = s[l:]
921
+ }
922
+ return t
923
+ }
924
+
925
+ // isSeparator reports whether the rune could mark a word boundary.
926
+ func isSeparator(r rune) bool {
927
+ if r <= 0x7F {
928
+ switch {
929
+ case '0' <= r && r <= '9':
930
+ return false
931
+ case 'a' <= r && r <= 'z':
932
+ return false
933
+ case 'A' <= r && r <= 'Z':
934
+ return false
935
+ case r == '_':
936
+ return false
937
+ }
938
+ return true
939
+ }
940
+ if unicode.IsLetter(r) || unicode.IsDigit(r) {
941
+ return false
942
+ }
943
+ return unicode.IsSpace(r)
944
+ }
945
+
946
+ // appendRune appends the UTF-8 encoding of r to p, writing RuneError for a
947
+ // value that is not a valid code point.
948
+ // The continuation bytes mask a byte(r>>n) rather than r>>n: the JS backend
949
+ // drops the parentheses around a wrapped int32 shift in `x | r>>n&m`.
950
+ func appendRune(p []byte, r rune) []byte {
951
+ switch {
952
+ case r < 0 || r > 0x10FFFF || (r >= 0xD800 && r <= 0xDFFF):
953
+ r = runeError
954
+ case r < 0x80:
955
+ return append(p, byte(r))
956
+ }
957
+ switch {
958
+ case r < 0x800:
959
+ return append(p, byte(0xC0|r>>6), byte(0x80|r&0x3F))
960
+ case r < 0x10000:
961
+ return append(p, byte(0xE0|r>>12), 0x80|byte(r>>6)&0x3F, byte(0x80|r&0x3F))
962
+ }
963
+ return append(p, byte(0xF0|r>>18), 0x80|byte(r>>12)&0x3F, 0x80|byte(r>>6)&0x3F, byte(0x80|r&0x3F))
964
+ }
965
+
966
+ // Title treats s as UTF-8-encoded bytes and returns a copy with all Unicode
967
+ // letters that begin words mapped to their title case.
968
+ //
969
+ // Deprecated: The rule Title uses for word boundaries does not handle Unicode
970
+ // punctuation properly.
971
+ func Title(s []byte) []byte {
972
+ prev := rune(' ')
973
+ out := make([]byte, 0, len(s))
974
+ for i := 0; i < len(s); {
975
+ r, size := decodeRune(s[i:])
976
+ i += size
977
+ c := r
978
+ if isSeparator(prev) {
979
+ c = unicode.ToTitle(r)
980
+ }
981
+ prev = r
982
+ if c >= 0 {
983
+ out = appendRune(out, c)
984
+ }
985
+ }
986
+ return out
987
+ }
988
+
989
+ // TrimLeftFunc treats s as UTF-8-encoded bytes and returns a subslice of s by slicing off
990
+ // all leading UTF-8-encoded code points c that satisfy f(c).
991
+ func TrimLeftFunc(s []byte, f func(r rune) bool) []byte {
992
+ i := indexFunc(s, f, false)
993
+ if i == -1 {
994
+ return nil
995
+ }
996
+ return s[i:]
997
+ }
998
+
999
+ // TrimRightFunc returns a subslice of s by slicing off all trailing
1000
+ // UTF-8-encoded code points c that satisfy f(c).
1001
+ func TrimRightFunc(s []byte, f func(r rune) bool) []byte {
1002
+ i := lastIndexFunc(s, f, false)
1003
+ if i >= 0 && s[i] >= runeSelf {
1004
+ _, wid := decodeRune(s[i:])
1005
+ i += wid
1006
+ } else {
1007
+ i++
1008
+ }
1009
+ return s[0:i]
1010
+ }