gofront 1.7.0 → 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 +13 -13
- package/package.json +8 -37
- package/src/backend/js/expressions.js +1341 -148
- package/src/backend/js/fmt-runtime.js +573 -0
- package/src/backend/js/index.js +375 -57
- package/src/backend/js/runtime.js +1460 -133
- package/src/backend/js/statements.js +900 -86
- 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 +2 -1
- package/src/backend/js/stdlib/fmt.js +349 -10
- package/src/backend/js/stdlib/index.js +8 -3
- package/src/backend/js/stdlib/json.js +247 -52
- 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 +10 -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 +436 -80
- package/src/backend/wasm/emit-builtins.js +303 -13
- package/src/backend/wasm/emit-exprs.js +1397 -203
- package/src/backend/wasm/emit-maps.js +61 -13
- package/src/backend/wasm/emit-stmts.js +1359 -164
- package/src/backend/wasm/emit.js +512 -77
- package/src/backend/wasm/encode.js +43 -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/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 +0 -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 +293 -28
- package/src/backend/wasm/stdlib/time.js +1041 -12
- package/src/backend/wasm/types.js +200 -15
- package/src/backend/wasm/variadic.js +93 -0
- package/src/backend/wasm/wat.js +47 -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} +3 -4
- package/src/compiler.js +107 -269
- 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 -1
- package/src/lower/captures.js +176 -32
- 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/{templ-parser.js → parser/templ.js} +138 -15
- package/src/parser/types.js +69 -9
- package/src/resolver.js +22 -1
- package/src/typechecker/assignability.js +176 -17
- package/src/typechecker/const-fold.js +356 -0
- package/src/typechecker/constants.js +256 -0
- package/src/typechecker/expressions.js +931 -122
- package/src/typechecker/index.js +459 -67
- package/src/typechecker/init-order.js +330 -0
- package/src/typechecker/resolve.js +451 -56
- package/src/typechecker/statements.js +90 -9
- package/src/typechecker/stdlib/core.js +333 -55
- package/src/typechecker/stdlib/excluded.js +898 -0
- package/src/typechecker/stdlib/extended.js +322 -26
- package/src/typechecker/{stdlib.js → stdlib/index.js} +5 -5
- package/src/typechecker/stdlib/simd.js +65 -15
- package/src/typechecker/termination.js +1 -1
- package/src/typechecker/types.js +149 -25
- 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,738 @@
|
|
|
1
|
+
// Copyright 2010 The Go Authors. All rights reserved.
|
|
2
|
+
// Use of this source code is governed by a BSD-style
|
|
3
|
+
// license that can be found in the LICENSE file.
|
|
4
|
+
|
|
5
|
+
//go:build gofront
|
|
6
|
+
|
|
7
|
+
//gofront:target both
|
|
8
|
+
|
|
9
|
+
package jsonrt
|
|
10
|
+
|
|
11
|
+
import (
|
|
12
|
+
"encoding/base64"
|
|
13
|
+
"errors"
|
|
14
|
+
"fmt"
|
|
15
|
+
"math"
|
|
16
|
+
"strconv"
|
|
17
|
+
"strings"
|
|
18
|
+
"unicode/utf8"
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
// An UnmarshalTypeError describes a JSON value that was not appropriate for
|
|
22
|
+
// a value of a specific Go type.
|
|
23
|
+
type UnmarshalTypeError struct {
|
|
24
|
+
Value string // description of JSON value - "bool", "array", "number -5"
|
|
25
|
+
Type string // type of Go value it could not be assigned to
|
|
26
|
+
Offset int64 // error occurred after reading Offset bytes
|
|
27
|
+
Struct string // name of the struct type containing the field
|
|
28
|
+
Field string // the full path from the root struct to the value
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
func (e *UnmarshalTypeError) Error() string {
|
|
32
|
+
if e.Struct != "" || e.Field != "" {
|
|
33
|
+
return "json: cannot unmarshal " + e.Value + " into Go struct field " + e.Struct + "." + e.Field + " of type " + e.Type
|
|
34
|
+
}
|
|
35
|
+
return "json: cannot unmarshal " + e.Value + " into Go value of type " + e.Type
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// An InvalidUnmarshalError describes an invalid argument passed to Unmarshal.
|
|
39
|
+
type InvalidUnmarshalError struct {
|
|
40
|
+
Type string // "" for a nil argument
|
|
41
|
+
IsPtr bool
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
func (e *InvalidUnmarshalError) Error() string {
|
|
45
|
+
if e.Type == "" {
|
|
46
|
+
return "json: Unmarshal(nil)"
|
|
47
|
+
}
|
|
48
|
+
if !e.IsPtr {
|
|
49
|
+
return "json: Unmarshal(non-pointer " + e.Type + ")"
|
|
50
|
+
}
|
|
51
|
+
return "json: Unmarshal(nil " + e.Type + ")"
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
var (
|
|
55
|
+
OptEscapeHTML = true
|
|
56
|
+
OptUseNumber bool
|
|
57
|
+
OptDisallowUnknownFields bool
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
// Dec is the state of one Unmarshal call. The input has been checked to be
|
|
61
|
+
// valid JSON, so the readers below do not look for syntax errors.
|
|
62
|
+
type Dec struct {
|
|
63
|
+
data []byte
|
|
64
|
+
pos int
|
|
65
|
+
Err error
|
|
66
|
+
fatal bool
|
|
67
|
+
structs []string
|
|
68
|
+
fields []string
|
|
69
|
+
key string
|
|
70
|
+
UseNumber bool
|
|
71
|
+
DisallowUnknownFields bool
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// NewDec checks that data is one valid JSON value and returns a decoder
|
|
75
|
+
// positioned at it.
|
|
76
|
+
func NewDec(data []byte) (*Dec, error) {
|
|
77
|
+
if err := CheckValid(data); err != nil {
|
|
78
|
+
return nil, err
|
|
79
|
+
}
|
|
80
|
+
return &Dec{
|
|
81
|
+
data: data,
|
|
82
|
+
UseNumber: OptUseNumber,
|
|
83
|
+
DisallowUnknownFields: OptDisallowUnknownFields,
|
|
84
|
+
}, nil
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// UnknownField records an error when an unknown struct field is encountered with DisallowUnknownFields.
|
|
88
|
+
func (d *Dec) UnknownField(field string) {
|
|
89
|
+
d.Save(fmt.Errorf("json: unknown field %q", field))
|
|
90
|
+
d.Skip()
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// InvalidUnmarshal is the error for a Unmarshal target v that is not a pointer
|
|
94
|
+
// to a type the compiler generated a decoder for.
|
|
95
|
+
func InvalidUnmarshal(v any) error {
|
|
96
|
+
if v == nil {
|
|
97
|
+
return &InvalidUnmarshalError{}
|
|
98
|
+
}
|
|
99
|
+
name := fmt.Sprintf("%T", v)
|
|
100
|
+
return &InvalidUnmarshalError{Type: name, IsPtr: strings.HasPrefix(name, "*")}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Done returns the first error found while decoding, if any.
|
|
104
|
+
func (d *Dec) Done() error {
|
|
105
|
+
return d.Err
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Fatal records an error from an Unmarshaler; decoding stops at once.
|
|
109
|
+
func (d *Dec) Fatal(err error) {
|
|
110
|
+
d.Err = err
|
|
111
|
+
d.fatal = true
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// Failed reports whether decoding was stopped by Fatal.
|
|
115
|
+
func (d *Dec) Failed() bool {
|
|
116
|
+
return d.fatal
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// Enter and Leave track the struct field being decoded for error messages.
|
|
120
|
+
func (d *Dec) Enter(structName, field string) {
|
|
121
|
+
d.structs = append(d.structs, structName)
|
|
122
|
+
d.fields = append(d.fields, field)
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
func (d *Dec) Leave() {
|
|
126
|
+
n := len(d.fields) - 1
|
|
127
|
+
d.structs = d.structs[:n]
|
|
128
|
+
d.fields = d.fields[:n]
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
func (d *Dec) ws() {
|
|
132
|
+
for d.pos < len(d.data) {
|
|
133
|
+
c := d.data[d.pos]
|
|
134
|
+
if c == ' ' || c == '\t' || c == '\n' || c == '\r' {
|
|
135
|
+
d.pos++
|
|
136
|
+
} else {
|
|
137
|
+
return
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
func (d *Dec) peek() byte {
|
|
143
|
+
d.ws()
|
|
144
|
+
if d.pos >= len(d.data) {
|
|
145
|
+
return 0
|
|
146
|
+
}
|
|
147
|
+
return d.data[d.pos]
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// kind names the JSON value at the current position.
|
|
151
|
+
func (d *Dec) kind() string {
|
|
152
|
+
switch d.peek() {
|
|
153
|
+
case '"':
|
|
154
|
+
return "string"
|
|
155
|
+
case '{':
|
|
156
|
+
return "object"
|
|
157
|
+
case '[':
|
|
158
|
+
return "array"
|
|
159
|
+
case 't', 'f':
|
|
160
|
+
return "bool"
|
|
161
|
+
case 'n':
|
|
162
|
+
return "null"
|
|
163
|
+
}
|
|
164
|
+
return "number"
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
func (d *Dec) typeErr(value, typ string) {
|
|
168
|
+
if d.Err != nil {
|
|
169
|
+
return
|
|
170
|
+
}
|
|
171
|
+
e := &UnmarshalTypeError{Value: value, Type: typ, Offset: int64(d.pos)}
|
|
172
|
+
if len(d.fields) > 0 {
|
|
173
|
+
e.Struct = d.structs[len(d.structs)-1]
|
|
174
|
+
e.Field = strings.Join(d.fields, ".")
|
|
175
|
+
}
|
|
176
|
+
d.Err = e
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// Mismatch records a type error for the next value, which cannot be stored
|
|
180
|
+
// in a value of type typ, and skips it.
|
|
181
|
+
func (d *Dec) Mismatch(typ string) {
|
|
182
|
+
if d.fatal {
|
|
183
|
+
return
|
|
184
|
+
}
|
|
185
|
+
k := d.kind()
|
|
186
|
+
d.Skip()
|
|
187
|
+
d.typeErr(k, typ)
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// IsArray reports whether the next value is an array.
|
|
191
|
+
func (d *Dec) IsArray() bool {
|
|
192
|
+
return d.peek() == '['
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// Bytes decodes a base64 string into a byte slice. ok is false for null and
|
|
196
|
+
// for a value that is not a string (an error is recorded unless it is null).
|
|
197
|
+
func (d *Dec) Bytes(typ string) (v []byte, ok bool) {
|
|
198
|
+
s, ok := d.String(typ)
|
|
199
|
+
if !ok {
|
|
200
|
+
return nil, false
|
|
201
|
+
}
|
|
202
|
+
b, err := base64.StdEncoding.DecodeString(s)
|
|
203
|
+
if err != nil {
|
|
204
|
+
d.Save(err)
|
|
205
|
+
return nil, false
|
|
206
|
+
}
|
|
207
|
+
return b, true
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// KeyInt parses the current object member name as an integer map key.
|
|
211
|
+
func (d *Dec) KeyInt(bits int, signed bool, typ string) (int64, bool) {
|
|
212
|
+
s := d.key
|
|
213
|
+
if signed {
|
|
214
|
+
n, err := strconv.ParseInt(s, 10, bits)
|
|
215
|
+
if err != nil {
|
|
216
|
+
d.typeErr("number "+s, typ)
|
|
217
|
+
return 0, false
|
|
218
|
+
}
|
|
219
|
+
return n, true
|
|
220
|
+
}
|
|
221
|
+
n, err := strconv.ParseUint(s, 10, bits)
|
|
222
|
+
if err != nil {
|
|
223
|
+
d.typeErr("number "+s, typ)
|
|
224
|
+
return 0, false
|
|
225
|
+
}
|
|
226
|
+
return int64(n), true
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// Unquote reads the string value of a ,string field and returns a decoder
|
|
230
|
+
// for the JSON text inside it, which must be a literal of the given kind
|
|
231
|
+
// ("string", "bool" or "number"). It returns nil for null, and for a value
|
|
232
|
+
// that does not qualify, after recording Go's error.
|
|
233
|
+
func (d *Dec) Unquote(typ, kind string) *Dec {
|
|
234
|
+
if d.fatal || d.Null() {
|
|
235
|
+
return nil
|
|
236
|
+
}
|
|
237
|
+
if d.peek() != '"' {
|
|
238
|
+
d.Save(errors.New("json: invalid use of ,string struct tag, trying to unmarshal unquoted value into " + typ))
|
|
239
|
+
d.Skip()
|
|
240
|
+
return nil
|
|
241
|
+
}
|
|
242
|
+
s := d.readString()
|
|
243
|
+
b := []byte(s)
|
|
244
|
+
if s == "null" {
|
|
245
|
+
return nil
|
|
246
|
+
}
|
|
247
|
+
ok := len(b) > 0 && CheckValid(b) == nil
|
|
248
|
+
if ok {
|
|
249
|
+
c := b[0]
|
|
250
|
+
switch kind {
|
|
251
|
+
case "string":
|
|
252
|
+
ok = c == '"'
|
|
253
|
+
case "bool":
|
|
254
|
+
ok = c == 't' || c == 'f'
|
|
255
|
+
default:
|
|
256
|
+
ok = c == '-' || (c >= '0' && c <= '9')
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
if !ok {
|
|
260
|
+
d.Save(errors.New("json: invalid use of ,string struct tag, trying to unmarshal " + strconv.Quote(s) + " into " + typ))
|
|
261
|
+
return nil
|
|
262
|
+
}
|
|
263
|
+
return &Dec{data: b, structs: d.structs, fields: d.fields}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
// Merge takes over the first error of a decoder made by Unquote.
|
|
267
|
+
func (d *Dec) Merge(sub *Dec) {
|
|
268
|
+
if d.Err == nil {
|
|
269
|
+
d.Err = sub.Err
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// Save records a non-fatal error (the first one wins).
|
|
274
|
+
func (d *Dec) Save(err error) {
|
|
275
|
+
if d.Err == nil {
|
|
276
|
+
d.Err = err
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
// Null consumes a null and reports whether there was one.
|
|
281
|
+
func (d *Dec) Null() bool {
|
|
282
|
+
if d.fatal {
|
|
283
|
+
return true
|
|
284
|
+
}
|
|
285
|
+
if d.peek() == 'n' {
|
|
286
|
+
d.pos += 4
|
|
287
|
+
return true
|
|
288
|
+
}
|
|
289
|
+
return false
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
// IsNull reports whether the next value is null, without consuming it.
|
|
293
|
+
func (d *Dec) IsNull() bool {
|
|
294
|
+
return d.peek() == 'n'
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
// Skip consumes the next value.
|
|
298
|
+
func (d *Dec) Skip() {
|
|
299
|
+
switch d.peek() {
|
|
300
|
+
case '"':
|
|
301
|
+
d.skipString()
|
|
302
|
+
case '{', '[':
|
|
303
|
+
d.skipContainer()
|
|
304
|
+
default:
|
|
305
|
+
d.skipScalar()
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
func (d *Dec) skipContainer() {
|
|
310
|
+
depth := 0
|
|
311
|
+
for d.pos < len(d.data) {
|
|
312
|
+
c := d.data[d.pos]
|
|
313
|
+
if c == '"' {
|
|
314
|
+
d.skipString()
|
|
315
|
+
continue
|
|
316
|
+
}
|
|
317
|
+
d.pos++
|
|
318
|
+
if c == '{' || c == '[' {
|
|
319
|
+
depth++
|
|
320
|
+
} else if c == '}' || c == ']' {
|
|
321
|
+
depth--
|
|
322
|
+
if depth == 0 {
|
|
323
|
+
return
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
func (d *Dec) skipScalar() {
|
|
330
|
+
for d.pos < len(d.data) {
|
|
331
|
+
c := d.data[d.pos]
|
|
332
|
+
if c == ',' || c == ']' || c == '}' || c == ' ' || c == '\t' || c == '\n' || c == '\r' {
|
|
333
|
+
return
|
|
334
|
+
}
|
|
335
|
+
d.pos++
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
func (d *Dec) skipString() {
|
|
340
|
+
d.pos++ // opening quote
|
|
341
|
+
for d.pos < len(d.data) {
|
|
342
|
+
c := d.data[d.pos]
|
|
343
|
+
d.pos++
|
|
344
|
+
if c == '\\' {
|
|
345
|
+
d.pos++
|
|
346
|
+
} else if c == '"' {
|
|
347
|
+
return
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
// Raw consumes the next value and returns a copy of its bytes.
|
|
353
|
+
func (d *Dec) Raw() []byte {
|
|
354
|
+
d.ws()
|
|
355
|
+
start := d.pos
|
|
356
|
+
d.Skip()
|
|
357
|
+
out := make([]byte, d.pos-start)
|
|
358
|
+
copy(out, d.data[start:d.pos])
|
|
359
|
+
return out
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
// Offset is the number of input bytes consumed so far.
|
|
363
|
+
func (d *Dec) Offset() int {
|
|
364
|
+
return d.pos
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
func (d *Dec) readNumber() string {
|
|
368
|
+
start := d.pos
|
|
369
|
+
for d.pos < len(d.data) {
|
|
370
|
+
c := d.data[d.pos]
|
|
371
|
+
if c >= '0' && c <= '9' || c == '-' || c == '+' || c == '.' || c == 'e' || c == 'E' {
|
|
372
|
+
d.pos++
|
|
373
|
+
} else {
|
|
374
|
+
break
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
return string(d.data[start:d.pos])
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
// Number decodes a number or string as a Number. ok is false for null.
|
|
381
|
+
func (d *Dec) Number(typ string) (string, bool) {
|
|
382
|
+
if d.fatal || d.Null() {
|
|
383
|
+
return "", false
|
|
384
|
+
}
|
|
385
|
+
if d.peek() == '"' {
|
|
386
|
+
s, ok := d.String(typ)
|
|
387
|
+
if !ok {
|
|
388
|
+
return "", false
|
|
389
|
+
}
|
|
390
|
+
if !isValidNumber(s) {
|
|
391
|
+
d.Save(fmt.Errorf("json: invalid number literal, trying to unmarshal %q into Number", s))
|
|
392
|
+
return "", false
|
|
393
|
+
}
|
|
394
|
+
return s, true
|
|
395
|
+
}
|
|
396
|
+
if d.kind() == "number" {
|
|
397
|
+
return d.readNumber(), true
|
|
398
|
+
}
|
|
399
|
+
d.Mismatch(typ)
|
|
400
|
+
return "", false
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
// Bool decodes a bool. ok is false for null (leave the target alone) and for
|
|
404
|
+
// a value of another kind (a type error is recorded).
|
|
405
|
+
func (d *Dec) Bool(typ string) (v bool, ok bool) {
|
|
406
|
+
if d.fatal || d.Null() {
|
|
407
|
+
return false, false
|
|
408
|
+
}
|
|
409
|
+
c := d.peek()
|
|
410
|
+
if c == 't' {
|
|
411
|
+
d.pos += 4
|
|
412
|
+
return true, true
|
|
413
|
+
}
|
|
414
|
+
if c == 'f' {
|
|
415
|
+
d.pos += 5
|
|
416
|
+
return false, true
|
|
417
|
+
}
|
|
418
|
+
k := d.kind()
|
|
419
|
+
d.Skip()
|
|
420
|
+
d.typeErr(k, typ)
|
|
421
|
+
return false, false
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
// String decodes a string.
|
|
425
|
+
func (d *Dec) String(typ string) (v string, ok bool) {
|
|
426
|
+
if d.fatal || d.Null() {
|
|
427
|
+
return "", false
|
|
428
|
+
}
|
|
429
|
+
if d.peek() != '"' {
|
|
430
|
+
k := d.kind()
|
|
431
|
+
d.Skip()
|
|
432
|
+
d.typeErr(k, typ)
|
|
433
|
+
return "", false
|
|
434
|
+
}
|
|
435
|
+
return d.readString(), true
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
// Int decodes an integer that must fit in bits bits.
|
|
439
|
+
func (d *Dec) Int(bits int, typ string) (v int64, ok bool) {
|
|
440
|
+
if d.fatal || d.Null() {
|
|
441
|
+
return 0, false
|
|
442
|
+
}
|
|
443
|
+
if d.peek() == '"' || d.peek() == '{' || d.peek() == '[' || d.peek() == 't' || d.peek() == 'f' {
|
|
444
|
+
k := d.kind()
|
|
445
|
+
d.Skip()
|
|
446
|
+
d.typeErr(k, typ)
|
|
447
|
+
return 0, false
|
|
448
|
+
}
|
|
449
|
+
s := d.readNumber()
|
|
450
|
+
n, err := strconv.ParseInt(s, 10, bits)
|
|
451
|
+
if err != nil {
|
|
452
|
+
d.typeErr("number "+s, typ)
|
|
453
|
+
return 0, false
|
|
454
|
+
}
|
|
455
|
+
return n, true
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
// Uint decodes an unsigned integer that must fit in bits bits.
|
|
459
|
+
func (d *Dec) Uint(bits int, typ string) (v uint64, ok bool) {
|
|
460
|
+
if d.fatal || d.Null() {
|
|
461
|
+
return 0, false
|
|
462
|
+
}
|
|
463
|
+
if d.peek() == '"' || d.peek() == '{' || d.peek() == '[' || d.peek() == 't' || d.peek() == 'f' {
|
|
464
|
+
k := d.kind()
|
|
465
|
+
d.Skip()
|
|
466
|
+
d.typeErr(k, typ)
|
|
467
|
+
return 0, false
|
|
468
|
+
}
|
|
469
|
+
s := d.readNumber()
|
|
470
|
+
n, err := strconv.ParseUint(s, 10, bits)
|
|
471
|
+
if err != nil {
|
|
472
|
+
d.typeErr("number "+s, typ)
|
|
473
|
+
return 0, false
|
|
474
|
+
}
|
|
475
|
+
return n, true
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
// Float decodes a floating-point number of the given size.
|
|
479
|
+
func (d *Dec) Float(bits int, typ string) (v float64, ok bool) {
|
|
480
|
+
if d.fatal || d.Null() {
|
|
481
|
+
return 0, false
|
|
482
|
+
}
|
|
483
|
+
if d.peek() == '"' || d.peek() == '{' || d.peek() == '[' || d.peek() == 't' || d.peek() == 'f' {
|
|
484
|
+
k := d.kind()
|
|
485
|
+
d.Skip()
|
|
486
|
+
d.typeErr(k, typ)
|
|
487
|
+
return 0, false
|
|
488
|
+
}
|
|
489
|
+
s := d.readNumber()
|
|
490
|
+
n, err := strconv.ParseFloat(s, bits)
|
|
491
|
+
if bits == 32 {
|
|
492
|
+
// Round to float32 here: the number may be out of float32 range.
|
|
493
|
+
n = float64(float32(n))
|
|
494
|
+
}
|
|
495
|
+
if err != nil || math.IsInf(n, 0) {
|
|
496
|
+
d.typeErr("number "+s, typ)
|
|
497
|
+
return 0, false
|
|
498
|
+
}
|
|
499
|
+
return n, true
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
// ObjBegin consumes the opening brace of an object. When the value is not an
|
|
503
|
+
// object it records a type error, skips the value and returns false.
|
|
504
|
+
func (d *Dec) ObjBegin(typ string) bool {
|
|
505
|
+
if d.fatal {
|
|
506
|
+
return false
|
|
507
|
+
}
|
|
508
|
+
if d.peek() != '{' {
|
|
509
|
+
k := d.kind()
|
|
510
|
+
d.Skip()
|
|
511
|
+
d.typeErr(k, typ)
|
|
512
|
+
return false
|
|
513
|
+
}
|
|
514
|
+
d.pos++
|
|
515
|
+
return true
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
// NextKey moves to the next member of an object; false at the closing brace.
|
|
519
|
+
// The member name is then available from Key.
|
|
520
|
+
func (d *Dec) NextKey() bool {
|
|
521
|
+
if d.fatal {
|
|
522
|
+
return false
|
|
523
|
+
}
|
|
524
|
+
c := d.peek()
|
|
525
|
+
if c == '}' {
|
|
526
|
+
d.pos++
|
|
527
|
+
return false
|
|
528
|
+
}
|
|
529
|
+
if c == ',' {
|
|
530
|
+
d.pos++
|
|
531
|
+
}
|
|
532
|
+
d.ws()
|
|
533
|
+
d.key = d.readString()
|
|
534
|
+
d.ws()
|
|
535
|
+
d.pos++ // the colon
|
|
536
|
+
return true
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
// Key is the name of the member NextKey moved to.
|
|
540
|
+
func (d *Dec) Key() string {
|
|
541
|
+
return d.key
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
// ArrBegin consumes the opening bracket of an array.
|
|
545
|
+
func (d *Dec) ArrBegin(typ string) bool {
|
|
546
|
+
if d.fatal {
|
|
547
|
+
return false
|
|
548
|
+
}
|
|
549
|
+
if d.peek() != '[' {
|
|
550
|
+
k := d.kind()
|
|
551
|
+
d.Skip()
|
|
552
|
+
d.typeErr(k, typ)
|
|
553
|
+
return false
|
|
554
|
+
}
|
|
555
|
+
d.pos++
|
|
556
|
+
return true
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
// NextElem moves to the next element of an array; false at the closing bracket.
|
|
560
|
+
func (d *Dec) NextElem() bool {
|
|
561
|
+
if d.fatal {
|
|
562
|
+
return false
|
|
563
|
+
}
|
|
564
|
+
c := d.peek()
|
|
565
|
+
if c == ']' {
|
|
566
|
+
d.pos++
|
|
567
|
+
return false
|
|
568
|
+
}
|
|
569
|
+
if c == ',' {
|
|
570
|
+
d.pos++
|
|
571
|
+
}
|
|
572
|
+
return true
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
// EqualFold reports whether two member names match ignoring case.
|
|
576
|
+
func EqualFold(a, b string) bool {
|
|
577
|
+
return strings.EqualFold(a, b)
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
// readString consumes the string at the current position.
|
|
581
|
+
func (d *Dec) readString() string {
|
|
582
|
+
d.pos++ // opening quote
|
|
583
|
+
start := d.pos
|
|
584
|
+
plain := true
|
|
585
|
+
for d.pos < len(d.data) {
|
|
586
|
+
c := d.data[d.pos]
|
|
587
|
+
if c == '"' {
|
|
588
|
+
break
|
|
589
|
+
}
|
|
590
|
+
if c == '\\' {
|
|
591
|
+
plain = false
|
|
592
|
+
d.pos++
|
|
593
|
+
} else if c >= utf8.RuneSelf {
|
|
594
|
+
plain = false
|
|
595
|
+
}
|
|
596
|
+
d.pos++
|
|
597
|
+
}
|
|
598
|
+
raw := d.data[start:d.pos]
|
|
599
|
+
d.pos++ // closing quote
|
|
600
|
+
if plain {
|
|
601
|
+
return string(raw)
|
|
602
|
+
}
|
|
603
|
+
return unquote(raw)
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
func getu4(s []byte, i int) rune {
|
|
607
|
+
if i+4 > len(s) {
|
|
608
|
+
return -1
|
|
609
|
+
}
|
|
610
|
+
var r rune
|
|
611
|
+
for j := i; j < i+4; j++ {
|
|
612
|
+
c := s[j]
|
|
613
|
+
switch {
|
|
614
|
+
case '0' <= c && c <= '9':
|
|
615
|
+
c = c - '0'
|
|
616
|
+
case 'a' <= c && c <= 'f':
|
|
617
|
+
c = c - 'a' + 10
|
|
618
|
+
case 'A' <= c && c <= 'F':
|
|
619
|
+
c = c - 'A' + 10
|
|
620
|
+
default:
|
|
621
|
+
return -1
|
|
622
|
+
}
|
|
623
|
+
r = r*16 + rune(c)
|
|
624
|
+
}
|
|
625
|
+
return r
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
// unquoteU decodes the \\u escape whose 'u' is at s[r], with a following
|
|
629
|
+
// \\u surrogate half when there is one. It returns the rune and the index of
|
|
630
|
+
// the first byte after the escape.
|
|
631
|
+
func unquoteU(s []byte, r int) (rune, int) {
|
|
632
|
+
rr := getu4(s, r+1)
|
|
633
|
+
r += 5
|
|
634
|
+
if rr >= 0xD800 && rr < 0xDC00 {
|
|
635
|
+
if r+1 < len(s) && s[r] == '\\' && s[r+1] == 'u' {
|
|
636
|
+
rr1 := getu4(s, r+2)
|
|
637
|
+
if rr1 >= 0xDC00 && rr1 < 0xE000 {
|
|
638
|
+
return 0x10000 + (rr-0xD800)<<10 + (rr1 - 0xDC00), r + 6
|
|
639
|
+
}
|
|
640
|
+
}
|
|
641
|
+
return utf8.RuneError, r
|
|
642
|
+
}
|
|
643
|
+
if rr >= 0xDC00 && rr < 0xE000 {
|
|
644
|
+
return utf8.RuneError, r
|
|
645
|
+
}
|
|
646
|
+
return rr, r
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
// unquote decodes the escapes of a JSON string body and coerces it to
|
|
650
|
+
// well-formed UTF-8.
|
|
651
|
+
func unquote(s []byte) string {
|
|
652
|
+
out := make([]byte, 0, len(s))
|
|
653
|
+
r := 0
|
|
654
|
+
for r < len(s) {
|
|
655
|
+
c := s[r]
|
|
656
|
+
if c == '\\' {
|
|
657
|
+
r++
|
|
658
|
+
switch s[r] {
|
|
659
|
+
case 'b':
|
|
660
|
+
out = append(out, '\b')
|
|
661
|
+
r++
|
|
662
|
+
case 'f':
|
|
663
|
+
out = append(out, '\f')
|
|
664
|
+
r++
|
|
665
|
+
case 'n':
|
|
666
|
+
out = append(out, '\n')
|
|
667
|
+
r++
|
|
668
|
+
case 'r':
|
|
669
|
+
out = append(out, '\r')
|
|
670
|
+
r++
|
|
671
|
+
case 't':
|
|
672
|
+
out = append(out, '\t')
|
|
673
|
+
r++
|
|
674
|
+
case 'u':
|
|
675
|
+
var rr rune
|
|
676
|
+
rr, r = unquoteU(s, r)
|
|
677
|
+
out = utf8.AppendRune(out, rr)
|
|
678
|
+
default:
|
|
679
|
+
out = append(out, s[r])
|
|
680
|
+
r++
|
|
681
|
+
}
|
|
682
|
+
} else if c < utf8.RuneSelf {
|
|
683
|
+
out = append(out, c)
|
|
684
|
+
r++
|
|
685
|
+
} else {
|
|
686
|
+
rr, size := utf8.DecodeRune(s[r:])
|
|
687
|
+
r += size
|
|
688
|
+
out = utf8.AppendRune(out, rr)
|
|
689
|
+
}
|
|
690
|
+
}
|
|
691
|
+
return string(out)
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
// Any decodes the next value into the empty interface: map[string]any,
|
|
695
|
+
// []any, float64, string, bool or nil.
|
|
696
|
+
func (d *Dec) Any() any {
|
|
697
|
+
if d.fatal {
|
|
698
|
+
return nil
|
|
699
|
+
}
|
|
700
|
+
switch d.peek() {
|
|
701
|
+
case '{':
|
|
702
|
+
d.pos++
|
|
703
|
+
m := make(map[string]any)
|
|
704
|
+
for d.NextKey() {
|
|
705
|
+
k := d.key
|
|
706
|
+
m[k] = d.Any()
|
|
707
|
+
}
|
|
708
|
+
return m
|
|
709
|
+
case '[':
|
|
710
|
+
d.pos++
|
|
711
|
+
a := make([]any, 0)
|
|
712
|
+
for d.NextElem() {
|
|
713
|
+
a = append(a, d.Any())
|
|
714
|
+
}
|
|
715
|
+
return a
|
|
716
|
+
case '"':
|
|
717
|
+
return d.readString()
|
|
718
|
+
case 't':
|
|
719
|
+
d.pos += 4
|
|
720
|
+
return true
|
|
721
|
+
case 'f':
|
|
722
|
+
d.pos += 5
|
|
723
|
+
return false
|
|
724
|
+
case 'n':
|
|
725
|
+
d.pos += 4
|
|
726
|
+
return nil
|
|
727
|
+
}
|
|
728
|
+
s := d.readNumber()
|
|
729
|
+
if d.UseNumber {
|
|
730
|
+
return Number(s)
|
|
731
|
+
}
|
|
732
|
+
f, err := strconv.ParseFloat(s, 64)
|
|
733
|
+
if err != nil {
|
|
734
|
+
d.typeErr("number "+s, "float64")
|
|
735
|
+
return nil
|
|
736
|
+
}
|
|
737
|
+
return f
|
|
738
|
+
}
|