gofront 1.6.1 → 1.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +45 -49
- package/package.json +12 -8
- package/src/backend/js/expressions.js +1627 -148
- package/src/backend/js/fmt-runtime.js +573 -0
- package/src/backend/js/index.js +508 -102
- package/src/backend/js/runtime.js +1997 -106
- package/src/backend/js/statements.js +931 -87
- package/src/backend/js/stdlib/bits.js +87 -14
- package/src/backend/js/stdlib/builder.js +41 -6
- package/src/backend/js/stdlib/bytes.js +253 -7
- package/src/backend/js/stdlib/errors.js +7 -1
- package/src/backend/js/stdlib/fmt.js +349 -10
- package/src/backend/js/stdlib/index.js +19 -2
- package/src/backend/js/stdlib/json.js +1167 -0
- package/src/backend/js/stdlib/maps.js +0 -8
- package/src/backend/js/stdlib/math.js +17 -1
- package/src/backend/js/stdlib/simd.js +34 -0
- package/src/backend/js/stdlib/slices.js +36 -6
- package/src/backend/js/stdlib/strconv.js +10 -5
- package/src/backend/js/stdlib/strings.js +83 -4
- package/src/backend/js/stdlib/testing.js +7 -0
- package/src/backend/js/stdlib/time.js +79 -55
- package/src/backend/js/stdlib/unicode.js +1 -1
- package/src/backend/js/stdlib/utf8.js +1 -1
- package/src/backend/js/templ.js +38 -76
- package/src/backend/js/type-info.js +272 -0
- package/src/backend/shared/fmt-types.js +188 -0
- package/src/backend/wasm/boundary.js +446 -72
- package/src/backend/wasm/emit-builtins.js +320 -13
- package/src/backend/wasm/emit-exprs.js +1404 -199
- package/src/backend/wasm/emit-maps.js +61 -13
- package/src/backend/wasm/emit-stmts.js +1359 -164
- package/src/backend/wasm/emit.js +518 -74
- package/src/backend/wasm/encode.js +128 -13
- package/src/backend/wasm/globals.js +452 -0
- package/src/backend/wasm/index.js +194 -2489
- package/src/backend/wasm/method-expr.js +381 -0
- package/src/backend/wasm/module-emitter.js +2240 -0
- package/src/backend/wasm/monomorph.js +62 -4
- package/src/backend/wasm/optimize.js +4 -2
- package/src/backend/wasm/prescan.js +397 -0
- package/src/backend/wasm/stdlib/bytes.js +1804 -127
- package/src/backend/wasm/stdlib/core.js +1574 -199
- package/src/backend/wasm/stdlib/index.js +3 -5
- package/src/backend/wasm/stdlib/io.js +1567 -150
- package/src/backend/wasm/stdlib/packages.js +2 -0
- package/src/backend/wasm/stdlib/simd.js +499 -0
- package/src/backend/wasm/stdlib/time.js +1041 -12
- package/src/backend/wasm/types.js +221 -15
- package/src/backend/wasm/variadic.js +93 -0
- package/src/backend/wasm/wat.js +84 -20
- package/src/{cli-core.js → cli/cli-core.js} +236 -10
- package/src/{test-runner.js → cli/test-runner.js} +332 -39
- package/src/{vendor.js → cli/vendor.js} +89 -15
- package/src/compiler.js +107 -269
- package/src/dts-parser.js +71 -14
- package/src/index.js +15 -169
- package/src/{lexer.js → lexer/lexer.js} +102 -55
- package/src/{tokens.js → lexer/tokens.js} +1 -0
- package/src/link/sourcemap.js +97 -0
- package/src/link/stdlib.js +515 -0
- package/src/link/wasm.js +294 -0
- package/src/lower/bounds.js +394 -0
- package/src/lower/boxing.js +1 -6
- package/src/lower/captures.js +176 -32
- package/src/lower/embedding.js +2 -1
- package/src/lower/index.js +26 -18
- package/src/lower/json-codecs.js +1398 -0
- package/src/lower/ownership.js +22 -1
- package/src/lower/range.js +86 -1
- package/src/lower/reachability.js +132 -0
- package/src/parser/declarations.js +58 -13
- package/src/parser/expressions.js +29 -7
- package/src/parser/index.js +2 -1
- package/src/parser/statements.js +37 -22
- package/src/parser/struct-tag.js +144 -0
- package/src/{templ-parser.js → parser/templ.js} +138 -15
- package/src/parser/types.js +130 -13
- package/src/resolver.js +22 -1
- package/src/typechecker/assignability.js +215 -11
- package/src/typechecker/const-fold.js +356 -0
- package/src/typechecker/constants.js +256 -0
- package/src/typechecker/expressions.js +960 -99
- package/src/typechecker/index.js +491 -72
- package/src/typechecker/init-order.js +330 -0
- package/src/typechecker/resolve.js +596 -52
- package/src/typechecker/statements.js +157 -17
- package/src/typechecker/stdlib/core.js +333 -55
- package/src/typechecker/stdlib/excluded.js +898 -0
- package/src/typechecker/stdlib/extended.js +359 -26
- package/src/typechecker/{stdlib.js → stdlib/index.js} +6 -4
- package/src/typechecker/stdlib/simd.js +123 -0
- package/src/typechecker/termination.js +1 -1
- package/src/typechecker/types.js +165 -26
- package/stdlib/bytes/iter.go +192 -0
- package/stdlib/bytes/search.go +240 -0
- package/stdlib/bytes/split.go +218 -0
- package/stdlib/cmp/cmp.go +65 -0
- package/stdlib/encoding/json/errors.go +31 -0
- package/stdlib/encoding/json/indent.go +71 -0
- package/stdlib/encoding/json/number.go +12 -0
- package/stdlib/encoding/json/stream.go +173 -0
- package/stdlib/errors/overlay.go +12 -0
- package/stdlib/hash/hash.go +53 -0
- package/stdlib/internal/jsonrt/dec.go +738 -0
- package/stdlib/internal/jsonrt/enc.go +366 -0
- package/stdlib/internal/jsonrt/indent.go +135 -0
- package/stdlib/internal/jsonrt/number.go +27 -0
- package/stdlib/internal/jsonrt/reader.go +73 -0
- package/stdlib/internal/jsonrt/scanner.go +649 -0
- package/stdlib/io/io.go +346 -0
- package/stdlib/iter/iter.go +18 -0
- package/stdlib/maps/iter.go +65 -0
- package/stdlib/math/extra.go +270 -0
- package/stdlib/slices/extra.go +73 -0
- package/stdlib/slices/iter.go +113 -0
- package/stdlib/sort/sort.go +561 -0
- package/stdlib/strconv/quote.go +341 -0
- package/stdlib/strings/extra.go +35 -0
- package/stdlib/strings/iter.go +122 -0
- package/stdlib/sync/extra.go +105 -0
- package/stdlib/unicode/unicode.go +112 -0
- package/stdlib/unicode/utf8/bytes.go +239 -0
- package/src/backend/wasm/const-fold.js +0 -205
- package/src/backend/wasm/emit-stdlib.js +0 -13
- /package/src/{asset-manager.js → cli/asset-manager.js} +0 -0
- /package/src/{colors.js → cli/colors.js} +0 -0
- /package/src/{dev-server.js → cli/dev-server.js} +0 -0
- /package/src/{minifier.js → cli/minifier.js} +0 -0
- /package/src/{project-config.js → cli/project-config.js} +0 -0
- /package/src/{pwa.js → cli/pwa.js} +0 -0
- /package/src/{templ-lexer.js → lexer/templ-lexer.js} +0 -0
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
//go:build gofront
|
|
2
|
+
|
|
3
|
+
//gofront:target both
|
|
4
|
+
|
|
5
|
+
// Overlay on the emitter-backed bytes package: search and comparison members
|
|
6
|
+
// written in Go and merged into the bytes namespace. They work on byte
|
|
7
|
+
// offsets and decode UTF-8 as Go does, so an invalid sequence reads as
|
|
8
|
+
// (RuneError, 1).
|
|
9
|
+
package bytes
|
|
10
|
+
|
|
11
|
+
import "unicode"
|
|
12
|
+
|
|
13
|
+
// decodeLastRune unpacks the last UTF-8 encoding in p and returns the rune and
|
|
14
|
+
// its width in bytes, as utf8.DecodeLastRune does: an invalid or incomplete
|
|
15
|
+
// encoding is (RuneError, 1) and p must not be empty.
|
|
16
|
+
func decodeLastRune(p []byte) (rune, int) {
|
|
17
|
+
end := len(p)
|
|
18
|
+
r := rune(p[end-1])
|
|
19
|
+
if r < runeSelf {
|
|
20
|
+
return r, 1
|
|
21
|
+
}
|
|
22
|
+
start := end - 1
|
|
23
|
+
lim := end - 4
|
|
24
|
+
if lim < 0 {
|
|
25
|
+
lim = 0
|
|
26
|
+
}
|
|
27
|
+
for start--; start >= lim; start-- {
|
|
28
|
+
if p[start]&0xC0 != 0x80 {
|
|
29
|
+
break
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
if start < 0 {
|
|
33
|
+
start = 0
|
|
34
|
+
}
|
|
35
|
+
r, size := decodeRune(p[start:end])
|
|
36
|
+
if start+size != end {
|
|
37
|
+
return runeError, 1
|
|
38
|
+
}
|
|
39
|
+
return r, size
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Compare returns an integer comparing two byte slices lexicographically.
|
|
43
|
+
// The result will be 0 if a == b, -1 if a < b, and +1 if a > b.
|
|
44
|
+
// A nil argument is equivalent to an empty slice.
|
|
45
|
+
func Compare(a, b []byte) int {
|
|
46
|
+
n := len(a)
|
|
47
|
+
if len(b) < n {
|
|
48
|
+
n = len(b)
|
|
49
|
+
}
|
|
50
|
+
for i := 0; i < n; i++ {
|
|
51
|
+
if a[i] != b[i] {
|
|
52
|
+
if a[i] < b[i] {
|
|
53
|
+
return -1
|
|
54
|
+
}
|
|
55
|
+
return 1
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
if len(a) < len(b) {
|
|
59
|
+
return -1
|
|
60
|
+
}
|
|
61
|
+
if len(a) > len(b) {
|
|
62
|
+
return 1
|
|
63
|
+
}
|
|
64
|
+
return 0
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// EqualFold reports whether s and t, interpreted as UTF-8 strings,
|
|
68
|
+
// are equal under simple Unicode case-folding, which is a more general
|
|
69
|
+
// form of case-insensitivity.
|
|
70
|
+
func EqualFold(s, t []byte) bool {
|
|
71
|
+
for len(s) != 0 && len(t) != 0 {
|
|
72
|
+
var sr, tr rune
|
|
73
|
+
if s[0] < runeSelf {
|
|
74
|
+
sr, s = rune(s[0]), s[1:]
|
|
75
|
+
} else {
|
|
76
|
+
r, size := decodeRune(s)
|
|
77
|
+
sr, s = r, s[size:]
|
|
78
|
+
}
|
|
79
|
+
if t[0] < runeSelf {
|
|
80
|
+
tr, t = rune(t[0]), t[1:]
|
|
81
|
+
} else {
|
|
82
|
+
r, size := decodeRune(t)
|
|
83
|
+
tr, t = r, t[size:]
|
|
84
|
+
}
|
|
85
|
+
if tr == sr {
|
|
86
|
+
continue
|
|
87
|
+
}
|
|
88
|
+
if tr < sr {
|
|
89
|
+
tr, sr = sr, tr
|
|
90
|
+
}
|
|
91
|
+
if tr < runeSelf {
|
|
92
|
+
if 'A' <= sr && sr <= 'Z' && tr == sr+'a'-'A' {
|
|
93
|
+
continue
|
|
94
|
+
}
|
|
95
|
+
return false
|
|
96
|
+
}
|
|
97
|
+
r := unicode.SimpleFold(sr)
|
|
98
|
+
for r != sr && r < tr {
|
|
99
|
+
r = unicode.SimpleFold(r)
|
|
100
|
+
}
|
|
101
|
+
if r == tr {
|
|
102
|
+
continue
|
|
103
|
+
}
|
|
104
|
+
return false
|
|
105
|
+
}
|
|
106
|
+
return len(s) == len(t)
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// IndexRune interprets s as a sequence of UTF-8-encoded code points.
|
|
110
|
+
// It returns the byte index of the first occurrence in s of the given rune.
|
|
111
|
+
// It returns -1 if rune is not present in s.
|
|
112
|
+
// If r is utf8.RuneError, it returns the first instance of any
|
|
113
|
+
// invalid UTF-8 byte sequence.
|
|
114
|
+
func IndexRune(s []byte, r rune) int {
|
|
115
|
+
if r < 0 || r > 0x10FFFF || (r >= 0xD800 && r <= 0xDFFF) {
|
|
116
|
+
return -1
|
|
117
|
+
}
|
|
118
|
+
if r < runeSelf {
|
|
119
|
+
return IndexByte(s, int(r))
|
|
120
|
+
}
|
|
121
|
+
for i := 0; i < len(s); {
|
|
122
|
+
c, size := decodeRune(s[i:])
|
|
123
|
+
if c == r {
|
|
124
|
+
return i
|
|
125
|
+
}
|
|
126
|
+
i += size
|
|
127
|
+
}
|
|
128
|
+
return -1
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// containsRuneIn reports whether chars contains r, treating an invalid sequence
|
|
132
|
+
// in chars as utf8.RuneError.
|
|
133
|
+
func containsRuneIn(chars string, r rune) bool {
|
|
134
|
+
for _, c := range chars {
|
|
135
|
+
if c == r {
|
|
136
|
+
return true
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
return false
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// IndexAny interprets s as a sequence of UTF-8-encoded Unicode code points.
|
|
143
|
+
// It returns the byte index of the first occurrence in s of any of the Unicode
|
|
144
|
+
// code points in chars. It returns -1 if chars is empty or if there is no code
|
|
145
|
+
// point in common.
|
|
146
|
+
func IndexAny(s []byte, chars string) int {
|
|
147
|
+
if len(chars) == 0 {
|
|
148
|
+
return -1
|
|
149
|
+
}
|
|
150
|
+
for i := 0; i < len(s); {
|
|
151
|
+
r, size := decodeRune(s[i:])
|
|
152
|
+
if containsRuneIn(chars, r) {
|
|
153
|
+
return i
|
|
154
|
+
}
|
|
155
|
+
i += size
|
|
156
|
+
}
|
|
157
|
+
return -1
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// LastIndexAny interprets s as a sequence of UTF-8-encoded Unicode code
|
|
161
|
+
// points. It returns the byte index of the last occurrence in s of any of
|
|
162
|
+
// the Unicode code points in chars. It returns -1 if chars is empty or if
|
|
163
|
+
// there is no code point in common.
|
|
164
|
+
func LastIndexAny(s []byte, chars string) int {
|
|
165
|
+
if len(chars) == 0 {
|
|
166
|
+
return -1
|
|
167
|
+
}
|
|
168
|
+
for i := len(s); i > 0; {
|
|
169
|
+
r, size := decodeLastRune(s[:i])
|
|
170
|
+
i -= size
|
|
171
|
+
if containsRuneIn(chars, r) {
|
|
172
|
+
return i
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
return -1
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
func indexFunc(s []byte, f func(rune) bool, truth bool) int {
|
|
179
|
+
for i := 0; i < len(s); {
|
|
180
|
+
r, size := decodeRune(s[i:])
|
|
181
|
+
if f(r) == truth {
|
|
182
|
+
return i
|
|
183
|
+
}
|
|
184
|
+
i += size
|
|
185
|
+
}
|
|
186
|
+
return -1
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
func lastIndexFunc(s []byte, f func(rune) bool, truth bool) int {
|
|
190
|
+
for i := len(s); i > 0; {
|
|
191
|
+
r, size := decodeLastRune(s[:i])
|
|
192
|
+
i -= size
|
|
193
|
+
if f(r) == truth {
|
|
194
|
+
return i
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
return -1
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// IndexFunc interprets s as a sequence of UTF-8-encoded code points.
|
|
201
|
+
// It returns the byte index in s of the first Unicode
|
|
202
|
+
// code point satisfying f(c), or -1 if none do.
|
|
203
|
+
func IndexFunc(s []byte, f func(r rune) bool) int {
|
|
204
|
+
return indexFunc(s, f, true)
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// LastIndexFunc interprets s as a sequence of UTF-8-encoded code points.
|
|
208
|
+
// It returns the byte index in s of the last Unicode
|
|
209
|
+
// code point satisfying f(c), or -1 if none do.
|
|
210
|
+
func LastIndexFunc(s []byte, f func(r rune) bool) int {
|
|
211
|
+
return lastIndexFunc(s, f, true)
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
// ContainsFunc reports whether any of the UTF-8-encoded code points
|
|
215
|
+
// in b satisfy f(c).
|
|
216
|
+
func ContainsFunc(b []byte, f func(rune) bool) bool {
|
|
217
|
+
return indexFunc(b, f, true) >= 0
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// CutPrefix returns s without the provided leading prefix byte slice
|
|
221
|
+
// and reports whether it found the prefix.
|
|
222
|
+
// If s doesn't start with prefix, CutPrefix returns s, false.
|
|
223
|
+
// If prefix is the empty byte slice, CutPrefix returns s, true.
|
|
224
|
+
func CutPrefix(s, prefix []byte) (after []byte, found bool) {
|
|
225
|
+
if len(s) < len(prefix) || Compare(s[:len(prefix)], prefix) != 0 {
|
|
226
|
+
return s, false
|
|
227
|
+
}
|
|
228
|
+
return s[len(prefix):], true
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// CutSuffix returns s without the provided ending suffix byte slice
|
|
232
|
+
// and reports whether it found the suffix.
|
|
233
|
+
// If s doesn't end with suffix, CutSuffix returns s, false.
|
|
234
|
+
// If suffix is the empty byte slice, CutSuffix returns s, true.
|
|
235
|
+
func CutSuffix(s, suffix []byte) (before []byte, found bool) {
|
|
236
|
+
if len(s) < len(suffix) || Compare(s[len(s)-len(suffix):], suffix) != 0 {
|
|
237
|
+
return s, false
|
|
238
|
+
}
|
|
239
|
+
return s[:len(s)-len(suffix)], true
|
|
240
|
+
}
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
//go:build gofront
|
|
2
|
+
|
|
3
|
+
//gofront:target both
|
|
4
|
+
|
|
5
|
+
// Overlay on the emitter-backed bytes package: splitting, trimming and
|
|
6
|
+
// case members written in Go and merged into the bytes namespace. Like Go's,
|
|
7
|
+
// the slices SplitAfter and SplitAfterN return alias the input and have their
|
|
8
|
+
// capacity clipped.
|
|
9
|
+
package bytes
|
|
10
|
+
|
|
11
|
+
import (
|
|
12
|
+
"errors"
|
|
13
|
+
"unicode"
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
// MinRead is the minimum slice size passed to a Read call by
|
|
17
|
+
// Buffer.ReadFrom. As long as the Buffer has at least MinRead bytes beyond
|
|
18
|
+
// what is required to hold the contents of r, ReadFrom will not grow the
|
|
19
|
+
// underlying buffer.
|
|
20
|
+
const MinRead = 512
|
|
21
|
+
|
|
22
|
+
// ErrTooLarge is passed to panic if memory cannot be allocated to store data in a buffer.
|
|
23
|
+
var ErrTooLarge = errors.New("bytes.Buffer: too large")
|
|
24
|
+
|
|
25
|
+
// runeCount returns the number of runes in p, counting each invalid byte as
|
|
26
|
+
// one rune as utf8.RuneCount does.
|
|
27
|
+
func runeCount(p []byte) int {
|
|
28
|
+
n := 0
|
|
29
|
+
for i := 0; i < len(p); n++ {
|
|
30
|
+
_, size := decodeRune(p[i:])
|
|
31
|
+
i += size
|
|
32
|
+
}
|
|
33
|
+
return n
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// countSep counts the non-overlapping instances of sep in s; sep must not be
|
|
37
|
+
// empty.
|
|
38
|
+
func countSep(s, sep []byte) int {
|
|
39
|
+
n := 0
|
|
40
|
+
for {
|
|
41
|
+
i := index(s, sep)
|
|
42
|
+
if i < 0 {
|
|
43
|
+
return n
|
|
44
|
+
}
|
|
45
|
+
n++
|
|
46
|
+
s = s[i+len(sep):]
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// explode splits s into a slice of UTF-8 sequences, one per Unicode code point
|
|
51
|
+
// (still slices of bytes), up to a maximum of n byte slices. Invalid UTF-8
|
|
52
|
+
// sequences are chopped into individual bytes.
|
|
53
|
+
func explode(s []byte, n int) [][]byte {
|
|
54
|
+
l := runeCount(s)
|
|
55
|
+
if n < 0 || n > l {
|
|
56
|
+
n = l
|
|
57
|
+
}
|
|
58
|
+
a := make([][]byte, n)
|
|
59
|
+
for i := 0; i < n-1; i++ {
|
|
60
|
+
_, size := decodeRune(s)
|
|
61
|
+
a[i] = s[:size:size]
|
|
62
|
+
s = s[size:]
|
|
63
|
+
}
|
|
64
|
+
if n > 0 {
|
|
65
|
+
a[n-1] = s[:len(s):len(s)]
|
|
66
|
+
}
|
|
67
|
+
return a
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// genSplit splits s around sep, including sepSave bytes of sep in each
|
|
71
|
+
// subslice, into at most n subslices.
|
|
72
|
+
func genSplit(s, sep []byte, sepSave, n int) [][]byte {
|
|
73
|
+
if n == 0 {
|
|
74
|
+
return nil
|
|
75
|
+
}
|
|
76
|
+
if len(sep) == 0 {
|
|
77
|
+
return explode(s, n)
|
|
78
|
+
}
|
|
79
|
+
if n < 0 {
|
|
80
|
+
n = countSep(s, sep) + 1
|
|
81
|
+
}
|
|
82
|
+
if n > len(s)+1 {
|
|
83
|
+
n = len(s) + 1
|
|
84
|
+
}
|
|
85
|
+
a := make([][]byte, n)
|
|
86
|
+
n--
|
|
87
|
+
i := 0
|
|
88
|
+
for i < n {
|
|
89
|
+
m := index(s, sep)
|
|
90
|
+
if m < 0 {
|
|
91
|
+
break
|
|
92
|
+
}
|
|
93
|
+
a[i] = s[: m+sepSave : m+sepSave]
|
|
94
|
+
s = s[m+len(sep):]
|
|
95
|
+
i++
|
|
96
|
+
}
|
|
97
|
+
a[i] = s[:len(s):len(s)]
|
|
98
|
+
return a[:i+1]
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// SplitAfter slices s into all subslices after each instance of sep and
|
|
102
|
+
// returns a slice of those subslices.
|
|
103
|
+
// If sep is empty, SplitAfter splits after each UTF-8 sequence.
|
|
104
|
+
// It is equivalent to SplitAfterN with a count of -1.
|
|
105
|
+
func SplitAfter(s, sep []byte) [][]byte {
|
|
106
|
+
return genSplit(s, sep, len(sep), -1)
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// SplitAfterN slices s into subslices after each instance of sep and
|
|
110
|
+
// returns a slice of those subslices.
|
|
111
|
+
// The count determines the number of subslices to return:
|
|
112
|
+
// - n > 0: at most n subslices; the last subslice will be the unsplit remainder;
|
|
113
|
+
// - n == 0: the result is nil (zero subslices);
|
|
114
|
+
// - n < 0: all subslices.
|
|
115
|
+
func SplitAfterN(s, sep []byte, n int) [][]byte {
|
|
116
|
+
return genSplit(s, sep, len(sep), n)
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// Runes interprets s as a sequence of UTF-8-encoded code points.
|
|
120
|
+
// It returns a slice of runes (Unicode code points) equivalent to s.
|
|
121
|
+
func Runes(s []byte) []rune {
|
|
122
|
+
t := make([]rune, runeCount(s))
|
|
123
|
+
i := 0
|
|
124
|
+
for len(s) > 0 {
|
|
125
|
+
r, l := decodeRune(s)
|
|
126
|
+
t[i] = r
|
|
127
|
+
i++
|
|
128
|
+
s = s[l:]
|
|
129
|
+
}
|
|
130
|
+
return t
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// isSeparator reports whether the rune could mark a word boundary.
|
|
134
|
+
func isSeparator(r rune) bool {
|
|
135
|
+
if r <= 0x7F {
|
|
136
|
+
switch {
|
|
137
|
+
case '0' <= r && r <= '9':
|
|
138
|
+
return false
|
|
139
|
+
case 'a' <= r && r <= 'z':
|
|
140
|
+
return false
|
|
141
|
+
case 'A' <= r && r <= 'Z':
|
|
142
|
+
return false
|
|
143
|
+
case r == '_':
|
|
144
|
+
return false
|
|
145
|
+
}
|
|
146
|
+
return true
|
|
147
|
+
}
|
|
148
|
+
if unicode.IsLetter(int(r)) || unicode.IsDigit(int(r)) {
|
|
149
|
+
return false
|
|
150
|
+
}
|
|
151
|
+
return unicode.IsSpace(int(r))
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// appendRune appends the UTF-8 encoding of r to p, writing RuneError for a
|
|
155
|
+
// value that is not a valid code point.
|
|
156
|
+
// The continuation bytes mask a byte(r>>n) rather than r>>n: the JS backend
|
|
157
|
+
// drops the parentheses around a wrapped int32 shift in `x | r>>n&m`.
|
|
158
|
+
func appendRune(p []byte, r rune) []byte {
|
|
159
|
+
switch {
|
|
160
|
+
case r < 0 || r > 0x10FFFF || (r >= 0xD800 && r <= 0xDFFF):
|
|
161
|
+
r = runeError
|
|
162
|
+
case r < 0x80:
|
|
163
|
+
return append(p, byte(r))
|
|
164
|
+
}
|
|
165
|
+
switch {
|
|
166
|
+
case r < 0x800:
|
|
167
|
+
return append(p, byte(0xC0|r>>6), byte(0x80|r&0x3F))
|
|
168
|
+
case r < 0x10000:
|
|
169
|
+
return append(p, byte(0xE0|r>>12), 0x80|byte(r>>6)&0x3F, byte(0x80|r&0x3F))
|
|
170
|
+
}
|
|
171
|
+
return append(p, byte(0xF0|r>>18), 0x80|byte(r>>12)&0x3F, 0x80|byte(r>>6)&0x3F, byte(0x80|r&0x3F))
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// Title treats s as UTF-8-encoded bytes and returns a copy with all Unicode
|
|
175
|
+
// letters that begin words mapped to their title case.
|
|
176
|
+
//
|
|
177
|
+
// Deprecated: The rule Title uses for word boundaries does not handle Unicode
|
|
178
|
+
// punctuation properly.
|
|
179
|
+
func Title(s []byte) []byte {
|
|
180
|
+
prev := rune(' ')
|
|
181
|
+
out := make([]byte, 0, len(s))
|
|
182
|
+
for i := 0; i < len(s); {
|
|
183
|
+
r, size := decodeRune(s[i:])
|
|
184
|
+
i += size
|
|
185
|
+
c := r
|
|
186
|
+
if isSeparator(prev) {
|
|
187
|
+
c = unicode.ToTitle(r)
|
|
188
|
+
}
|
|
189
|
+
prev = r
|
|
190
|
+
if c >= 0 {
|
|
191
|
+
out = appendRune(out, c)
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
return out
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// TrimLeftFunc treats s as UTF-8-encoded bytes and returns a subslice of s by slicing off
|
|
198
|
+
// all leading UTF-8-encoded code points c that satisfy f(c).
|
|
199
|
+
func TrimLeftFunc(s []byte, f func(r rune) bool) []byte {
|
|
200
|
+
i := indexFunc(s, f, false)
|
|
201
|
+
if i == -1 {
|
|
202
|
+
return nil
|
|
203
|
+
}
|
|
204
|
+
return s[i:]
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// TrimRightFunc returns a subslice of s by slicing off all trailing
|
|
208
|
+
// UTF-8-encoded code points c that satisfy f(c).
|
|
209
|
+
func TrimRightFunc(s []byte, f func(r rune) bool) []byte {
|
|
210
|
+
i := lastIndexFunc(s, f, false)
|
|
211
|
+
if i >= 0 && s[i] >= runeSelf {
|
|
212
|
+
_, wid := decodeRune(s[i:])
|
|
213
|
+
i += wid
|
|
214
|
+
} else {
|
|
215
|
+
i++
|
|
216
|
+
}
|
|
217
|
+
return s[0:i]
|
|
218
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
//go:build gofront
|
|
2
|
+
|
|
3
|
+
//gofront:target both
|
|
4
|
+
|
|
5
|
+
// Package cmp provides types and functions related to comparing ordered
|
|
6
|
+
// values. Same API as Go's cmp package.
|
|
7
|
+
package cmp
|
|
8
|
+
|
|
9
|
+
// Ordered is a constraint that permits any ordered type: any type that
|
|
10
|
+
// supports the operators < <= >= >.
|
|
11
|
+
type Ordered interface {
|
|
12
|
+
~int | ~int8 | ~int16 | ~int32 | ~int64 |
|
|
13
|
+
~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr |
|
|
14
|
+
~float32 | ~float64 |
|
|
15
|
+
~string
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// Less reports whether x is less than y. A NaN is less than any non-NaN,
|
|
19
|
+
// and -0.0 is not less than 0.0.
|
|
20
|
+
func Less[T Ordered](x, y T) bool {
|
|
21
|
+
return (isNaNValue(x) && !isNaNValue(y)) || x < y
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Compare returns -1 if x is less than y, 0 if x equals y, and +1 if x is
|
|
25
|
+
// greater than y. A NaN is less than any non-NaN, a NaN equals a NaN, and
|
|
26
|
+
// -0.0 equals 0.0.
|
|
27
|
+
func Compare[T Ordered](x, y T) int {
|
|
28
|
+
xNaN := isNaNValue(x)
|
|
29
|
+
yNaN := isNaNValue(y)
|
|
30
|
+
if xNaN {
|
|
31
|
+
if yNaN {
|
|
32
|
+
return 0
|
|
33
|
+
}
|
|
34
|
+
return -1
|
|
35
|
+
}
|
|
36
|
+
if yNaN {
|
|
37
|
+
return +1
|
|
38
|
+
}
|
|
39
|
+
if x < y {
|
|
40
|
+
return -1
|
|
41
|
+
}
|
|
42
|
+
if x > y {
|
|
43
|
+
return +1
|
|
44
|
+
}
|
|
45
|
+
return 0
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// isNaNValue reports whether x is a NaN without requiring the math package
|
|
49
|
+
// (named so it does not collide with the browser global isNaN until Task 0.9).
|
|
50
|
+
// This will always return false if T is not floating-point.
|
|
51
|
+
func isNaNValue[T Ordered](x T) bool {
|
|
52
|
+
return x != x
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Or returns the first of its arguments that is not equal to the zero
|
|
56
|
+
// value. If no argument is non-zero, it returns the zero value.
|
|
57
|
+
func Or[T comparable](vals ...T) T {
|
|
58
|
+
var zero T
|
|
59
|
+
for _, v := range vals {
|
|
60
|
+
if v != zero {
|
|
61
|
+
return v
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return zero
|
|
65
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
//go:build gofront
|
|
2
|
+
|
|
3
|
+
//gofront:target both
|
|
4
|
+
|
|
5
|
+
package json
|
|
6
|
+
|
|
7
|
+
import (
|
|
8
|
+
"internal/jsonrt"
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
// A SyntaxError is a description of a JSON syntax error.
|
|
12
|
+
// [Unmarshal] will return a SyntaxError if the JSON can't be parsed.
|
|
13
|
+
type SyntaxError = jsonrt.SyntaxError
|
|
14
|
+
|
|
15
|
+
// An UnmarshalTypeError describes a JSON value that was not appropriate for
|
|
16
|
+
// a value of a specific Go type.
|
|
17
|
+
type UnmarshalTypeError = jsonrt.UnmarshalTypeError
|
|
18
|
+
|
|
19
|
+
// An InvalidUnmarshalError describes an invalid argument passed to Unmarshal.
|
|
20
|
+
type InvalidUnmarshalError = jsonrt.InvalidUnmarshalError
|
|
21
|
+
|
|
22
|
+
// An UnsupportedValueError is returned by Marshal when attempting to encode
|
|
23
|
+
// an unsupported value.
|
|
24
|
+
type UnsupportedValueError = jsonrt.UnsupportedValueError
|
|
25
|
+
|
|
26
|
+
// UnsupportedTypeError is returned by Marshal when attempting to encode an
|
|
27
|
+
// unsupported value type.
|
|
28
|
+
type UnsupportedTypeError = jsonrt.UnsupportedTypeError
|
|
29
|
+
|
|
30
|
+
// A MarshalerError represents an error from calling a MarshalJSON method.
|
|
31
|
+
type MarshalerError = jsonrt.MarshalerError
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
//go:build gofront
|
|
2
|
+
|
|
3
|
+
//gofront:target both
|
|
4
|
+
|
|
5
|
+
package json
|
|
6
|
+
|
|
7
|
+
import (
|
|
8
|
+
"bytes"
|
|
9
|
+
"internal/jsonrt"
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
var hexDigits = []byte("0123456789abcdef")
|
|
13
|
+
|
|
14
|
+
func escapeLen(src []byte, i int) int {
|
|
15
|
+
c := src[i]
|
|
16
|
+
if c == '<' || c == '>' || c == '&' {
|
|
17
|
+
return 1
|
|
18
|
+
}
|
|
19
|
+
if c == 0xE2 && i+2 < len(src) && src[i+1] == 0x80 && (src[i+2]&^1) == 0xA8 {
|
|
20
|
+
return 3
|
|
21
|
+
}
|
|
22
|
+
return 0
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// HTMLEscape appends to dst the JSON-encoded src with <, >, &, U+2028 and U+2029
|
|
26
|
+
// characters inside string literals changed to \u003c, \u003e, \u0026, \u2028, \u2029
|
|
27
|
+
// so that the JSON will be safe to embed inside HTML <script> tags.
|
|
28
|
+
func HTMLEscape(dst *bytes.Buffer, src []byte) {
|
|
29
|
+
start := 0
|
|
30
|
+
for i := 0; i < len(src); {
|
|
31
|
+
n := escapeLen(src, i)
|
|
32
|
+
if n == 0 {
|
|
33
|
+
i++
|
|
34
|
+
continue
|
|
35
|
+
}
|
|
36
|
+
if start < i {
|
|
37
|
+
dst.Write(src[start:i])
|
|
38
|
+
}
|
|
39
|
+
if n == 1 {
|
|
40
|
+
c := src[i]
|
|
41
|
+
dst.Write([]byte{'\\', 'u', '0', '0', hexDigits[c>>4], hexDigits[c&0xF]})
|
|
42
|
+
i++
|
|
43
|
+
} else {
|
|
44
|
+
dst.Write([]byte{'\\', 'u', '2', '0', '2', hexDigits[src[i+2]&0xF]})
|
|
45
|
+
i += 3
|
|
46
|
+
}
|
|
47
|
+
start = i
|
|
48
|
+
}
|
|
49
|
+
if start < len(src) {
|
|
50
|
+
dst.Write(src[start:])
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Compact appends to dst the JSON-encoded src with
|
|
55
|
+
// insignificant space characters elided.
|
|
56
|
+
func Compact(dst *bytes.Buffer, src []byte) error {
|
|
57
|
+
b, err := jsonrt.AppendCompact(nil, src, false)
|
|
58
|
+
if len(b) > 0 {
|
|
59
|
+
dst.Write(b)
|
|
60
|
+
}
|
|
61
|
+
return err
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Indent appends to dst an indented form of the JSON-encoded src.
|
|
65
|
+
func Indent(dst *bytes.Buffer, src []byte, prefix, indent string) error {
|
|
66
|
+
b, err := jsonrt.AppendIndent(nil, src, prefix, indent)
|
|
67
|
+
if len(b) > 0 {
|
|
68
|
+
dst.Write(b)
|
|
69
|
+
}
|
|
70
|
+
return err
|
|
71
|
+
}
|