xref: /aosp_15_r20/external/golang-protobuf/internal/encoding/json/decode_test.go (revision 1c12ee1efe575feb122dbf939ff15148a3b3e8f2)
1*1c12ee1eSDan Willemsen// Copyright 2019 The Go Authors. All rights reserved.
2*1c12ee1eSDan Willemsen// Use of this source code is governed by a BSD-style
3*1c12ee1eSDan Willemsen// license that can be found in the LICENSE file.
4*1c12ee1eSDan Willemsen
5*1c12ee1eSDan Willemsenpackage json_test
6*1c12ee1eSDan Willemsen
7*1c12ee1eSDan Willemsenimport (
8*1c12ee1eSDan Willemsen	"fmt"
9*1c12ee1eSDan Willemsen	"math"
10*1c12ee1eSDan Willemsen	"strings"
11*1c12ee1eSDan Willemsen	"testing"
12*1c12ee1eSDan Willemsen	"unicode/utf8"
13*1c12ee1eSDan Willemsen
14*1c12ee1eSDan Willemsen	"github.com/google/go-cmp/cmp"
15*1c12ee1eSDan Willemsen
16*1c12ee1eSDan Willemsen	"google.golang.org/protobuf/internal/encoding/json"
17*1c12ee1eSDan Willemsen)
18*1c12ee1eSDan Willemsen
19*1c12ee1eSDan Willemsentype R struct {
20*1c12ee1eSDan Willemsen	// E is expected error substring from calling Decoder.Read if set.
21*1c12ee1eSDan Willemsen	E string
22*1c12ee1eSDan Willemsen	// V is one of the checker implementations that validates the token value.
23*1c12ee1eSDan Willemsen	V checker
24*1c12ee1eSDan Willemsen	// P is expected Token.Pos() if set > 0.
25*1c12ee1eSDan Willemsen	P int
26*1c12ee1eSDan Willemsen	// RS is expected result from Token.RawString() if not empty.
27*1c12ee1eSDan Willemsen	RS string
28*1c12ee1eSDan Willemsen}
29*1c12ee1eSDan Willemsen
30*1c12ee1eSDan Willemsen// checker defines API for Token validation.
31*1c12ee1eSDan Willemsentype checker interface {
32*1c12ee1eSDan Willemsen	// check checks and expects for token API call to return and compare
33*1c12ee1eSDan Willemsen	// against implementation-stored value. Returns empty string if success,
34*1c12ee1eSDan Willemsen	// else returns error message describing the error.
35*1c12ee1eSDan Willemsen	check(json.Token) string
36*1c12ee1eSDan Willemsen}
37*1c12ee1eSDan Willemsen
38*1c12ee1eSDan Willemsen// checkers that checks the token kind only.
39*1c12ee1eSDan Willemsenvar (
40*1c12ee1eSDan Willemsen	EOF         = kindOnly{json.EOF}
41*1c12ee1eSDan Willemsen	Null        = kindOnly{json.Null}
42*1c12ee1eSDan Willemsen	ObjectOpen  = kindOnly{json.ObjectOpen}
43*1c12ee1eSDan Willemsen	ObjectClose = kindOnly{json.ObjectClose}
44*1c12ee1eSDan Willemsen	ArrayOpen   = kindOnly{json.ArrayOpen}
45*1c12ee1eSDan Willemsen	ArrayClose  = kindOnly{json.ArrayClose}
46*1c12ee1eSDan Willemsen)
47*1c12ee1eSDan Willemsen
48*1c12ee1eSDan Willemsentype kindOnly struct {
49*1c12ee1eSDan Willemsen	want json.Kind
50*1c12ee1eSDan Willemsen}
51*1c12ee1eSDan Willemsen
52*1c12ee1eSDan Willemsenfunc (x kindOnly) check(tok json.Token) string {
53*1c12ee1eSDan Willemsen	if got := tok.Kind(); got != x.want {
54*1c12ee1eSDan Willemsen		return fmt.Sprintf("Token.Kind(): got %v, want %v", got, x.want)
55*1c12ee1eSDan Willemsen	}
56*1c12ee1eSDan Willemsen	return ""
57*1c12ee1eSDan Willemsen}
58*1c12ee1eSDan Willemsen
59*1c12ee1eSDan Willemsentype Name struct {
60*1c12ee1eSDan Willemsen	val string
61*1c12ee1eSDan Willemsen}
62*1c12ee1eSDan Willemsen
63*1c12ee1eSDan Willemsenfunc (x Name) check(tok json.Token) string {
64*1c12ee1eSDan Willemsen	if got := tok.Kind(); got != json.Name {
65*1c12ee1eSDan Willemsen		return fmt.Sprintf("Token.Kind(): got %v, want %v", got, json.Name)
66*1c12ee1eSDan Willemsen	}
67*1c12ee1eSDan Willemsen
68*1c12ee1eSDan Willemsen	if got := tok.Name(); got != x.val {
69*1c12ee1eSDan Willemsen		return fmt.Sprintf("Token.Name(): got %v, want %v", got, x.val)
70*1c12ee1eSDan Willemsen	}
71*1c12ee1eSDan Willemsen	return ""
72*1c12ee1eSDan Willemsen}
73*1c12ee1eSDan Willemsen
74*1c12ee1eSDan Willemsentype Bool struct {
75*1c12ee1eSDan Willemsen	val bool
76*1c12ee1eSDan Willemsen}
77*1c12ee1eSDan Willemsen
78*1c12ee1eSDan Willemsenfunc (x Bool) check(tok json.Token) string {
79*1c12ee1eSDan Willemsen	if got := tok.Kind(); got != json.Bool {
80*1c12ee1eSDan Willemsen		return fmt.Sprintf("Token.Kind(): got %v, want %v", got, json.Bool)
81*1c12ee1eSDan Willemsen	}
82*1c12ee1eSDan Willemsen
83*1c12ee1eSDan Willemsen	if got := tok.Bool(); got != x.val {
84*1c12ee1eSDan Willemsen		return fmt.Sprintf("Token.Bool(): got %v, want %v", got, x.val)
85*1c12ee1eSDan Willemsen	}
86*1c12ee1eSDan Willemsen	return ""
87*1c12ee1eSDan Willemsen}
88*1c12ee1eSDan Willemsen
89*1c12ee1eSDan Willemsentype Str struct {
90*1c12ee1eSDan Willemsen	val string
91*1c12ee1eSDan Willemsen}
92*1c12ee1eSDan Willemsen
93*1c12ee1eSDan Willemsenfunc (x Str) check(tok json.Token) string {
94*1c12ee1eSDan Willemsen	if got := tok.Kind(); got != json.String {
95*1c12ee1eSDan Willemsen		return fmt.Sprintf("Token.Kind(): got %v, want %v", got, json.String)
96*1c12ee1eSDan Willemsen	}
97*1c12ee1eSDan Willemsen
98*1c12ee1eSDan Willemsen	if got := tok.ParsedString(); got != x.val {
99*1c12ee1eSDan Willemsen		return fmt.Sprintf("Token.ParsedString(): got %v, want %v", got, x.val)
100*1c12ee1eSDan Willemsen	}
101*1c12ee1eSDan Willemsen	return ""
102*1c12ee1eSDan Willemsen}
103*1c12ee1eSDan Willemsen
104*1c12ee1eSDan Willemsentype F64 struct {
105*1c12ee1eSDan Willemsen	val float64
106*1c12ee1eSDan Willemsen}
107*1c12ee1eSDan Willemsen
108*1c12ee1eSDan Willemsenfunc (x F64) check(tok json.Token) string {
109*1c12ee1eSDan Willemsen	if got := tok.Kind(); got != json.Number {
110*1c12ee1eSDan Willemsen		return fmt.Sprintf("Token.Kind(): got %v, want %v", got, json.Number)
111*1c12ee1eSDan Willemsen	}
112*1c12ee1eSDan Willemsen
113*1c12ee1eSDan Willemsen	got, ok := tok.Float(64)
114*1c12ee1eSDan Willemsen	if !ok {
115*1c12ee1eSDan Willemsen		return fmt.Sprintf("Token.Float(64): returned not ok")
116*1c12ee1eSDan Willemsen	}
117*1c12ee1eSDan Willemsen	if got != x.val {
118*1c12ee1eSDan Willemsen		return fmt.Sprintf("Token.Float(64): got %v, want %v", got, x.val)
119*1c12ee1eSDan Willemsen	}
120*1c12ee1eSDan Willemsen	return ""
121*1c12ee1eSDan Willemsen}
122*1c12ee1eSDan Willemsen
123*1c12ee1eSDan Willemsentype F32 struct {
124*1c12ee1eSDan Willemsen	val float32
125*1c12ee1eSDan Willemsen}
126*1c12ee1eSDan Willemsen
127*1c12ee1eSDan Willemsenfunc (x F32) check(tok json.Token) string {
128*1c12ee1eSDan Willemsen	if got := tok.Kind(); got != json.Number {
129*1c12ee1eSDan Willemsen		return fmt.Sprintf("Token.Kind(): got %v, want %v", got, json.Number)
130*1c12ee1eSDan Willemsen	}
131*1c12ee1eSDan Willemsen
132*1c12ee1eSDan Willemsen	got, ok := tok.Float(32)
133*1c12ee1eSDan Willemsen	if !ok {
134*1c12ee1eSDan Willemsen		return fmt.Sprintf("Token.Float(32): returned not ok")
135*1c12ee1eSDan Willemsen	}
136*1c12ee1eSDan Willemsen	if float32(got) != x.val {
137*1c12ee1eSDan Willemsen		return fmt.Sprintf("Token.Float(32): got %v, want %v", got, x.val)
138*1c12ee1eSDan Willemsen	}
139*1c12ee1eSDan Willemsen	return ""
140*1c12ee1eSDan Willemsen}
141*1c12ee1eSDan Willemsen
142*1c12ee1eSDan Willemsen// NotF64 is a checker to validate a Number token where Token.Float(64) returns not ok.
143*1c12ee1eSDan Willemsenvar NotF64 = xf64{}
144*1c12ee1eSDan Willemsen
145*1c12ee1eSDan Willemsentype xf64 struct{}
146*1c12ee1eSDan Willemsen
147*1c12ee1eSDan Willemsenfunc (x xf64) check(tok json.Token) string {
148*1c12ee1eSDan Willemsen	if got := tok.Kind(); got != json.Number {
149*1c12ee1eSDan Willemsen		return fmt.Sprintf("Token.Kind(): got %v, want %v", got, json.Number)
150*1c12ee1eSDan Willemsen	}
151*1c12ee1eSDan Willemsen
152*1c12ee1eSDan Willemsen	_, ok := tok.Float(64)
153*1c12ee1eSDan Willemsen	if ok {
154*1c12ee1eSDan Willemsen		return fmt.Sprintf("Token.Float(64): returned ok")
155*1c12ee1eSDan Willemsen	}
156*1c12ee1eSDan Willemsen	return ""
157*1c12ee1eSDan Willemsen}
158*1c12ee1eSDan Willemsen
159*1c12ee1eSDan Willemsen// NotF32 is a checker to validate a Number token where Token.Float(32) returns not ok.
160*1c12ee1eSDan Willemsenvar NotF32 = xf32{}
161*1c12ee1eSDan Willemsen
162*1c12ee1eSDan Willemsentype xf32 struct{}
163*1c12ee1eSDan Willemsen
164*1c12ee1eSDan Willemsenfunc (x xf32) check(tok json.Token) string {
165*1c12ee1eSDan Willemsen	if got := tok.Kind(); got != json.Number {
166*1c12ee1eSDan Willemsen		return fmt.Sprintf("Token.Kind(): got %v, want %v", got, json.Number)
167*1c12ee1eSDan Willemsen	}
168*1c12ee1eSDan Willemsen
169*1c12ee1eSDan Willemsen	_, ok := tok.Float(32)
170*1c12ee1eSDan Willemsen	if ok {
171*1c12ee1eSDan Willemsen		return fmt.Sprintf("Token.Float(32): returned ok")
172*1c12ee1eSDan Willemsen	}
173*1c12ee1eSDan Willemsen	return ""
174*1c12ee1eSDan Willemsen}
175*1c12ee1eSDan Willemsen
176*1c12ee1eSDan Willemsentype I64 struct {
177*1c12ee1eSDan Willemsen	val int64
178*1c12ee1eSDan Willemsen}
179*1c12ee1eSDan Willemsen
180*1c12ee1eSDan Willemsenfunc (x I64) check(tok json.Token) string {
181*1c12ee1eSDan Willemsen	if got := tok.Kind(); got != json.Number {
182*1c12ee1eSDan Willemsen		return fmt.Sprintf("Token.Kind(): got %v, want %v", got, json.Number)
183*1c12ee1eSDan Willemsen	}
184*1c12ee1eSDan Willemsen
185*1c12ee1eSDan Willemsen	got, ok := tok.Int(64)
186*1c12ee1eSDan Willemsen	if !ok {
187*1c12ee1eSDan Willemsen		return fmt.Sprintf("Token.Int(64): returned not ok")
188*1c12ee1eSDan Willemsen	}
189*1c12ee1eSDan Willemsen	if got != x.val {
190*1c12ee1eSDan Willemsen		return fmt.Sprintf("Token.Int(64): got %v, want %v", got, x.val)
191*1c12ee1eSDan Willemsen	}
192*1c12ee1eSDan Willemsen	return ""
193*1c12ee1eSDan Willemsen}
194*1c12ee1eSDan Willemsen
195*1c12ee1eSDan Willemsentype I32 struct {
196*1c12ee1eSDan Willemsen	val int32
197*1c12ee1eSDan Willemsen}
198*1c12ee1eSDan Willemsen
199*1c12ee1eSDan Willemsenfunc (x I32) check(tok json.Token) string {
200*1c12ee1eSDan Willemsen	if got := tok.Kind(); got != json.Number {
201*1c12ee1eSDan Willemsen		return fmt.Sprintf("Token.Kind(): got %v, want %v", got, json.Number)
202*1c12ee1eSDan Willemsen	}
203*1c12ee1eSDan Willemsen
204*1c12ee1eSDan Willemsen	got, ok := tok.Int(32)
205*1c12ee1eSDan Willemsen	if !ok {
206*1c12ee1eSDan Willemsen		return fmt.Sprintf("Token.Int(32): returned not ok")
207*1c12ee1eSDan Willemsen	}
208*1c12ee1eSDan Willemsen	if int32(got) != x.val {
209*1c12ee1eSDan Willemsen		return fmt.Sprintf("Token.Int(32): got %v, want %v", got, x.val)
210*1c12ee1eSDan Willemsen	}
211*1c12ee1eSDan Willemsen	return ""
212*1c12ee1eSDan Willemsen}
213*1c12ee1eSDan Willemsen
214*1c12ee1eSDan Willemsen// NotI64 is a checker to validate a Number token where Token.Int(64) returns not ok.
215*1c12ee1eSDan Willemsenvar NotI64 = xi64{}
216*1c12ee1eSDan Willemsen
217*1c12ee1eSDan Willemsentype xi64 struct{}
218*1c12ee1eSDan Willemsen
219*1c12ee1eSDan Willemsenfunc (x xi64) check(tok json.Token) string {
220*1c12ee1eSDan Willemsen	if got := tok.Kind(); got != json.Number {
221*1c12ee1eSDan Willemsen		return fmt.Sprintf("Token.Kind(): got %v, want %v", got, json.Number)
222*1c12ee1eSDan Willemsen	}
223*1c12ee1eSDan Willemsen
224*1c12ee1eSDan Willemsen	_, ok := tok.Int(64)
225*1c12ee1eSDan Willemsen	if ok {
226*1c12ee1eSDan Willemsen		return fmt.Sprintf("Token.Int(64): returned ok")
227*1c12ee1eSDan Willemsen	}
228*1c12ee1eSDan Willemsen	return ""
229*1c12ee1eSDan Willemsen}
230*1c12ee1eSDan Willemsen
231*1c12ee1eSDan Willemsen// NotI32 is a checker to validate a Number token where Token.Int(32) returns not ok.
232*1c12ee1eSDan Willemsenvar NotI32 = xi32{}
233*1c12ee1eSDan Willemsen
234*1c12ee1eSDan Willemsentype xi32 struct{}
235*1c12ee1eSDan Willemsen
236*1c12ee1eSDan Willemsenfunc (x xi32) check(tok json.Token) string {
237*1c12ee1eSDan Willemsen	if got := tok.Kind(); got != json.Number {
238*1c12ee1eSDan Willemsen		return fmt.Sprintf("Token.Kind(): got %v, want %v", got, json.Number)
239*1c12ee1eSDan Willemsen	}
240*1c12ee1eSDan Willemsen
241*1c12ee1eSDan Willemsen	_, ok := tok.Int(32)
242*1c12ee1eSDan Willemsen	if ok {
243*1c12ee1eSDan Willemsen		return fmt.Sprintf("Token.Int(32): returned ok")
244*1c12ee1eSDan Willemsen	}
245*1c12ee1eSDan Willemsen	return ""
246*1c12ee1eSDan Willemsen}
247*1c12ee1eSDan Willemsen
248*1c12ee1eSDan Willemsentype Ui64 struct {
249*1c12ee1eSDan Willemsen	val uint64
250*1c12ee1eSDan Willemsen}
251*1c12ee1eSDan Willemsen
252*1c12ee1eSDan Willemsenfunc (x Ui64) check(tok json.Token) string {
253*1c12ee1eSDan Willemsen	if got := tok.Kind(); got != json.Number {
254*1c12ee1eSDan Willemsen		return fmt.Sprintf("Token.Kind(): got %v, want %v", got, json.Number)
255*1c12ee1eSDan Willemsen	}
256*1c12ee1eSDan Willemsen
257*1c12ee1eSDan Willemsen	got, ok := tok.Uint(64)
258*1c12ee1eSDan Willemsen	if !ok {
259*1c12ee1eSDan Willemsen		return fmt.Sprintf("Token.Uint(64): returned not ok")
260*1c12ee1eSDan Willemsen	}
261*1c12ee1eSDan Willemsen	if got != x.val {
262*1c12ee1eSDan Willemsen		return fmt.Sprintf("Token.Uint(64): got %v, want %v", got, x.val)
263*1c12ee1eSDan Willemsen	}
264*1c12ee1eSDan Willemsen	return ""
265*1c12ee1eSDan Willemsen}
266*1c12ee1eSDan Willemsen
267*1c12ee1eSDan Willemsentype Ui32 struct {
268*1c12ee1eSDan Willemsen	val uint32
269*1c12ee1eSDan Willemsen}
270*1c12ee1eSDan Willemsen
271*1c12ee1eSDan Willemsenfunc (x Ui32) check(tok json.Token) string {
272*1c12ee1eSDan Willemsen	if got := tok.Kind(); got != json.Number {
273*1c12ee1eSDan Willemsen		return fmt.Sprintf("Token.Kind(): got %v, want %v", got, json.Number)
274*1c12ee1eSDan Willemsen	}
275*1c12ee1eSDan Willemsen
276*1c12ee1eSDan Willemsen	got, ok := tok.Uint(32)
277*1c12ee1eSDan Willemsen	if !ok {
278*1c12ee1eSDan Willemsen		return fmt.Sprintf("Token.Uint(32): returned not ok")
279*1c12ee1eSDan Willemsen	}
280*1c12ee1eSDan Willemsen	if uint32(got) != x.val {
281*1c12ee1eSDan Willemsen		return fmt.Sprintf("Token.Uint(32): got %v, want %v", got, x.val)
282*1c12ee1eSDan Willemsen	}
283*1c12ee1eSDan Willemsen	return ""
284*1c12ee1eSDan Willemsen}
285*1c12ee1eSDan Willemsen
286*1c12ee1eSDan Willemsen// NotUi64 is a checker to validate a Number token where Token.Uint(64) returns not ok.
287*1c12ee1eSDan Willemsenvar NotUi64 = xui64{}
288*1c12ee1eSDan Willemsen
289*1c12ee1eSDan Willemsentype xui64 struct{}
290*1c12ee1eSDan Willemsen
291*1c12ee1eSDan Willemsenfunc (x xui64) check(tok json.Token) string {
292*1c12ee1eSDan Willemsen	if got := tok.Kind(); got != json.Number {
293*1c12ee1eSDan Willemsen		return fmt.Sprintf("Token.Kind(): got %v, want %v", got, json.Number)
294*1c12ee1eSDan Willemsen	}
295*1c12ee1eSDan Willemsen
296*1c12ee1eSDan Willemsen	_, ok := tok.Uint(64)
297*1c12ee1eSDan Willemsen	if ok {
298*1c12ee1eSDan Willemsen		return fmt.Sprintf("Token.Uint(64): returned ok")
299*1c12ee1eSDan Willemsen	}
300*1c12ee1eSDan Willemsen	return ""
301*1c12ee1eSDan Willemsen}
302*1c12ee1eSDan Willemsen
303*1c12ee1eSDan Willemsen// NotI32 is a checker to validate a Number token where Token.Uint(32) returns not ok.
304*1c12ee1eSDan Willemsenvar NotUi32 = xui32{}
305*1c12ee1eSDan Willemsen
306*1c12ee1eSDan Willemsentype xui32 struct{}
307*1c12ee1eSDan Willemsen
308*1c12ee1eSDan Willemsenfunc (x xui32) check(tok json.Token) string {
309*1c12ee1eSDan Willemsen	if got := tok.Kind(); got != json.Number {
310*1c12ee1eSDan Willemsen		return fmt.Sprintf("Token.Kind(): got %v, want %v", got, json.Number)
311*1c12ee1eSDan Willemsen	}
312*1c12ee1eSDan Willemsen
313*1c12ee1eSDan Willemsen	_, ok := tok.Uint(32)
314*1c12ee1eSDan Willemsen	if ok {
315*1c12ee1eSDan Willemsen		return fmt.Sprintf("Token.Uint(32): returned ok")
316*1c12ee1eSDan Willemsen	}
317*1c12ee1eSDan Willemsen	return ""
318*1c12ee1eSDan Willemsen}
319*1c12ee1eSDan Willemsen
320*1c12ee1eSDan Willemsenvar errEOF = json.ErrUnexpectedEOF.Error()
321*1c12ee1eSDan Willemsen
322*1c12ee1eSDan Willemsenfunc TestDecoder(t *testing.T) {
323*1c12ee1eSDan Willemsen	const space = " \n\r\t"
324*1c12ee1eSDan Willemsen
325*1c12ee1eSDan Willemsen	tests := []struct {
326*1c12ee1eSDan Willemsen		in string
327*1c12ee1eSDan Willemsen		// want is a list of expected values returned from calling
328*1c12ee1eSDan Willemsen		// Decoder.Read. An item makes the test code invoke
329*1c12ee1eSDan Willemsen		// Decoder.Read and compare against R.E for error returned or use R.V to
330*1c12ee1eSDan Willemsen		// validate the returned Token object.
331*1c12ee1eSDan Willemsen		want []R
332*1c12ee1eSDan Willemsen	}{
333*1c12ee1eSDan Willemsen		{
334*1c12ee1eSDan Willemsen			in:   ``,
335*1c12ee1eSDan Willemsen			want: []R{{V: EOF}},
336*1c12ee1eSDan Willemsen		},
337*1c12ee1eSDan Willemsen		{
338*1c12ee1eSDan Willemsen			in:   space,
339*1c12ee1eSDan Willemsen			want: []R{{V: EOF}},
340*1c12ee1eSDan Willemsen		},
341*1c12ee1eSDan Willemsen		{
342*1c12ee1eSDan Willemsen			// Calling Read after EOF will keep returning EOF for
343*1c12ee1eSDan Willemsen			// succeeding Read calls.
344*1c12ee1eSDan Willemsen			in: space,
345*1c12ee1eSDan Willemsen			want: []R{
346*1c12ee1eSDan Willemsen				{V: EOF},
347*1c12ee1eSDan Willemsen				{V: EOF},
348*1c12ee1eSDan Willemsen				{V: EOF},
349*1c12ee1eSDan Willemsen			},
350*1c12ee1eSDan Willemsen		},
351*1c12ee1eSDan Willemsen
352*1c12ee1eSDan Willemsen		// JSON literals.
353*1c12ee1eSDan Willemsen		{
354*1c12ee1eSDan Willemsen			in: space + `null` + space,
355*1c12ee1eSDan Willemsen			want: []R{
356*1c12ee1eSDan Willemsen				{V: Null, P: len(space), RS: `null`},
357*1c12ee1eSDan Willemsen				{V: EOF},
358*1c12ee1eSDan Willemsen			},
359*1c12ee1eSDan Willemsen		},
360*1c12ee1eSDan Willemsen		{
361*1c12ee1eSDan Willemsen			in: space + `true` + space,
362*1c12ee1eSDan Willemsen			want: []R{
363*1c12ee1eSDan Willemsen				{V: Bool{true}},
364*1c12ee1eSDan Willemsen				{V: EOF},
365*1c12ee1eSDan Willemsen			},
366*1c12ee1eSDan Willemsen		},
367*1c12ee1eSDan Willemsen		{
368*1c12ee1eSDan Willemsen			in: space + `false` + space,
369*1c12ee1eSDan Willemsen			want: []R{
370*1c12ee1eSDan Willemsen				{V: Bool{false}},
371*1c12ee1eSDan Willemsen				{V: EOF},
372*1c12ee1eSDan Willemsen			},
373*1c12ee1eSDan Willemsen		},
374*1c12ee1eSDan Willemsen		{
375*1c12ee1eSDan Willemsen			// Error returned will produce the same error again.
376*1c12ee1eSDan Willemsen			in: space + `foo` + space,
377*1c12ee1eSDan Willemsen			want: []R{
378*1c12ee1eSDan Willemsen				{E: `invalid value foo`},
379*1c12ee1eSDan Willemsen				{E: `invalid value foo`},
380*1c12ee1eSDan Willemsen			},
381*1c12ee1eSDan Willemsen		},
382*1c12ee1eSDan Willemsen
383*1c12ee1eSDan Willemsen		// JSON strings.
384*1c12ee1eSDan Willemsen		{
385*1c12ee1eSDan Willemsen			in: space + `""` + space,
386*1c12ee1eSDan Willemsen			want: []R{
387*1c12ee1eSDan Willemsen				{V: Str{}},
388*1c12ee1eSDan Willemsen				{V: EOF},
389*1c12ee1eSDan Willemsen			},
390*1c12ee1eSDan Willemsen		},
391*1c12ee1eSDan Willemsen		{
392*1c12ee1eSDan Willemsen			in: space + `"hello"` + space,
393*1c12ee1eSDan Willemsen			want: []R{
394*1c12ee1eSDan Willemsen				{V: Str{"hello"}, RS: `"hello"`},
395*1c12ee1eSDan Willemsen				{V: EOF},
396*1c12ee1eSDan Willemsen			},
397*1c12ee1eSDan Willemsen		},
398*1c12ee1eSDan Willemsen		{
399*1c12ee1eSDan Willemsen			in:   `"hello`,
400*1c12ee1eSDan Willemsen			want: []R{{E: errEOF}},
401*1c12ee1eSDan Willemsen		},
402*1c12ee1eSDan Willemsen		{
403*1c12ee1eSDan Willemsen			in:   "\"\x00\"",
404*1c12ee1eSDan Willemsen			want: []R{{E: `invalid character '\x00' in string`}},
405*1c12ee1eSDan Willemsen		},
406*1c12ee1eSDan Willemsen		{
407*1c12ee1eSDan Willemsen			in: "\"\u0031\u0032\"",
408*1c12ee1eSDan Willemsen			want: []R{
409*1c12ee1eSDan Willemsen				{V: Str{"12"}, RS: "\"\u0031\u0032\""},
410*1c12ee1eSDan Willemsen				{V: EOF},
411*1c12ee1eSDan Willemsen			},
412*1c12ee1eSDan Willemsen		},
413*1c12ee1eSDan Willemsen		{
414*1c12ee1eSDan Willemsen			// Invalid UTF-8 error is returned in ReadString instead of Read.
415*1c12ee1eSDan Willemsen			in:   "\"\xff\"",
416*1c12ee1eSDan Willemsen			want: []R{{E: `syntax error (line 1:1): invalid UTF-8 in string`}},
417*1c12ee1eSDan Willemsen		},
418*1c12ee1eSDan Willemsen		{
419*1c12ee1eSDan Willemsen			in: `"` + string(utf8.RuneError) + `"`,
420*1c12ee1eSDan Willemsen			want: []R{
421*1c12ee1eSDan Willemsen				{V: Str{string(utf8.RuneError)}},
422*1c12ee1eSDan Willemsen				{V: EOF},
423*1c12ee1eSDan Willemsen			},
424*1c12ee1eSDan Willemsen		},
425*1c12ee1eSDan Willemsen		{
426*1c12ee1eSDan Willemsen			in: `"\uFFFD"`,
427*1c12ee1eSDan Willemsen			want: []R{
428*1c12ee1eSDan Willemsen				{V: Str{string(utf8.RuneError)}},
429*1c12ee1eSDan Willemsen				{V: EOF},
430*1c12ee1eSDan Willemsen			},
431*1c12ee1eSDan Willemsen		},
432*1c12ee1eSDan Willemsen		{
433*1c12ee1eSDan Willemsen			in:   `"\x"`,
434*1c12ee1eSDan Willemsen			want: []R{{E: `invalid escape code "\\x" in string`}},
435*1c12ee1eSDan Willemsen		},
436*1c12ee1eSDan Willemsen		{
437*1c12ee1eSDan Willemsen			in:   `"\uXXXX"`,
438*1c12ee1eSDan Willemsen			want: []R{{E: `invalid escape code "\\uXXXX" in string`}},
439*1c12ee1eSDan Willemsen		},
440*1c12ee1eSDan Willemsen		{
441*1c12ee1eSDan Willemsen			in:   `"\uDEAD"`, // unmatched surrogate pair
442*1c12ee1eSDan Willemsen			want: []R{{E: errEOF}},
443*1c12ee1eSDan Willemsen		},
444*1c12ee1eSDan Willemsen		{
445*1c12ee1eSDan Willemsen			in:   `"\uDEAD\uBEEF"`, // invalid surrogate half
446*1c12ee1eSDan Willemsen			want: []R{{E: `invalid escape code "\\uBEEF" in string`}},
447*1c12ee1eSDan Willemsen		},
448*1c12ee1eSDan Willemsen		{
449*1c12ee1eSDan Willemsen			in: `"\uD800\udead"`, // valid surrogate pair
450*1c12ee1eSDan Willemsen			want: []R{
451*1c12ee1eSDan Willemsen				{V: Str{`��`}},
452*1c12ee1eSDan Willemsen				{V: EOF},
453*1c12ee1eSDan Willemsen			},
454*1c12ee1eSDan Willemsen		},
455*1c12ee1eSDan Willemsen		{
456*1c12ee1eSDan Willemsen			in: `"\u0000\"\\\/\b\f\n\r\t"`,
457*1c12ee1eSDan Willemsen			want: []R{
458*1c12ee1eSDan Willemsen				{V: Str{"\u0000\"\\/\b\f\n\r\t"}},
459*1c12ee1eSDan Willemsen				{V: EOF},
460*1c12ee1eSDan Willemsen			},
461*1c12ee1eSDan Willemsen		},
462*1c12ee1eSDan Willemsen
463*1c12ee1eSDan Willemsen		// Invalid JSON numbers.
464*1c12ee1eSDan Willemsen		{
465*1c12ee1eSDan Willemsen			in:   `-`,
466*1c12ee1eSDan Willemsen			want: []R{{E: `invalid value -`}},
467*1c12ee1eSDan Willemsen		},
468*1c12ee1eSDan Willemsen		{
469*1c12ee1eSDan Willemsen			in:   `+0`,
470*1c12ee1eSDan Willemsen			want: []R{{E: `invalid value +0`}},
471*1c12ee1eSDan Willemsen		},
472*1c12ee1eSDan Willemsen		{
473*1c12ee1eSDan Willemsen			in:   `-+`,
474*1c12ee1eSDan Willemsen			want: []R{{E: `invalid value -+`}},
475*1c12ee1eSDan Willemsen		},
476*1c12ee1eSDan Willemsen		{
477*1c12ee1eSDan Willemsen			in:   `0.`,
478*1c12ee1eSDan Willemsen			want: []R{{E: `invalid value 0.`}},
479*1c12ee1eSDan Willemsen		},
480*1c12ee1eSDan Willemsen		{
481*1c12ee1eSDan Willemsen			in:   `.1`,
482*1c12ee1eSDan Willemsen			want: []R{{E: `invalid value .1`}},
483*1c12ee1eSDan Willemsen		},
484*1c12ee1eSDan Willemsen		{
485*1c12ee1eSDan Willemsen			in:   `1.0.1`,
486*1c12ee1eSDan Willemsen			want: []R{{E: `invalid value 1.0.1`}},
487*1c12ee1eSDan Willemsen		},
488*1c12ee1eSDan Willemsen		{
489*1c12ee1eSDan Willemsen			in:   `1..1`,
490*1c12ee1eSDan Willemsen			want: []R{{E: `invalid value 1..1`}},
491*1c12ee1eSDan Willemsen		},
492*1c12ee1eSDan Willemsen		{
493*1c12ee1eSDan Willemsen			in:   `-1-2`,
494*1c12ee1eSDan Willemsen			want: []R{{E: `invalid value -1-2`}},
495*1c12ee1eSDan Willemsen		},
496*1c12ee1eSDan Willemsen		{
497*1c12ee1eSDan Willemsen			in:   `01`,
498*1c12ee1eSDan Willemsen			want: []R{{E: `invalid value 01`}},
499*1c12ee1eSDan Willemsen		},
500*1c12ee1eSDan Willemsen		{
501*1c12ee1eSDan Willemsen			in:   `1e`,
502*1c12ee1eSDan Willemsen			want: []R{{E: `invalid value 1e`}},
503*1c12ee1eSDan Willemsen		},
504*1c12ee1eSDan Willemsen		{
505*1c12ee1eSDan Willemsen			in:   `1e1.2`,
506*1c12ee1eSDan Willemsen			want: []R{{E: `invalid value 1e1.2`}},
507*1c12ee1eSDan Willemsen		},
508*1c12ee1eSDan Willemsen		{
509*1c12ee1eSDan Willemsen			in:   `1Ee`,
510*1c12ee1eSDan Willemsen			want: []R{{E: `invalid value 1Ee`}},
511*1c12ee1eSDan Willemsen		},
512*1c12ee1eSDan Willemsen		{
513*1c12ee1eSDan Willemsen			in:   `1.e1`,
514*1c12ee1eSDan Willemsen			want: []R{{E: `invalid value 1.e1`}},
515*1c12ee1eSDan Willemsen		},
516*1c12ee1eSDan Willemsen		{
517*1c12ee1eSDan Willemsen			in:   `1.e+`,
518*1c12ee1eSDan Willemsen			want: []R{{E: `invalid value 1.e+`}},
519*1c12ee1eSDan Willemsen		},
520*1c12ee1eSDan Willemsen		{
521*1c12ee1eSDan Willemsen			in:   `1e+-2`,
522*1c12ee1eSDan Willemsen			want: []R{{E: `invalid value 1e+-2`}},
523*1c12ee1eSDan Willemsen		},
524*1c12ee1eSDan Willemsen		{
525*1c12ee1eSDan Willemsen			in:   `1e--2`,
526*1c12ee1eSDan Willemsen			want: []R{{E: `invalid value 1e--2`}},
527*1c12ee1eSDan Willemsen		},
528*1c12ee1eSDan Willemsen		{
529*1c12ee1eSDan Willemsen			in:   `1.0true`,
530*1c12ee1eSDan Willemsen			want: []R{{E: `invalid value 1.0true`}},
531*1c12ee1eSDan Willemsen		},
532*1c12ee1eSDan Willemsen
533*1c12ee1eSDan Willemsen		// JSON numbers as floating point.
534*1c12ee1eSDan Willemsen		{
535*1c12ee1eSDan Willemsen			in: space + `0.0` + space,
536*1c12ee1eSDan Willemsen			want: []R{
537*1c12ee1eSDan Willemsen				{V: F32{0}, P: len(space), RS: `0.0`},
538*1c12ee1eSDan Willemsen				{V: EOF},
539*1c12ee1eSDan Willemsen			},
540*1c12ee1eSDan Willemsen		},
541*1c12ee1eSDan Willemsen		{
542*1c12ee1eSDan Willemsen			in: space + `0` + space,
543*1c12ee1eSDan Willemsen			want: []R{
544*1c12ee1eSDan Willemsen				{V: F32{0}},
545*1c12ee1eSDan Willemsen				{V: EOF},
546*1c12ee1eSDan Willemsen			},
547*1c12ee1eSDan Willemsen		},
548*1c12ee1eSDan Willemsen		{
549*1c12ee1eSDan Willemsen			in: space + `-0` + space,
550*1c12ee1eSDan Willemsen			want: []R{
551*1c12ee1eSDan Willemsen				{V: F32{float32(math.Copysign(0, -1))}},
552*1c12ee1eSDan Willemsen				{V: EOF},
553*1c12ee1eSDan Willemsen			},
554*1c12ee1eSDan Willemsen		},
555*1c12ee1eSDan Willemsen		{
556*1c12ee1eSDan Willemsen			in: `-0`,
557*1c12ee1eSDan Willemsen			want: []R{
558*1c12ee1eSDan Willemsen				{V: F64{math.Copysign(0, -1)}},
559*1c12ee1eSDan Willemsen				{V: EOF},
560*1c12ee1eSDan Willemsen			},
561*1c12ee1eSDan Willemsen		},
562*1c12ee1eSDan Willemsen		{
563*1c12ee1eSDan Willemsen			in: `-0.0`,
564*1c12ee1eSDan Willemsen			want: []R{
565*1c12ee1eSDan Willemsen				{V: F32{float32(math.Copysign(0, -1))}},
566*1c12ee1eSDan Willemsen				{V: EOF},
567*1c12ee1eSDan Willemsen			},
568*1c12ee1eSDan Willemsen		},
569*1c12ee1eSDan Willemsen		{
570*1c12ee1eSDan Willemsen			in: `-0.0`,
571*1c12ee1eSDan Willemsen			want: []R{
572*1c12ee1eSDan Willemsen				{V: F64{math.Copysign(0, -1)}},
573*1c12ee1eSDan Willemsen				{V: EOF},
574*1c12ee1eSDan Willemsen			},
575*1c12ee1eSDan Willemsen		},
576*1c12ee1eSDan Willemsen		{
577*1c12ee1eSDan Willemsen			in: `-1.02`,
578*1c12ee1eSDan Willemsen			want: []R{
579*1c12ee1eSDan Willemsen				{V: F32{-1.02}},
580*1c12ee1eSDan Willemsen				{V: EOF},
581*1c12ee1eSDan Willemsen			},
582*1c12ee1eSDan Willemsen		},
583*1c12ee1eSDan Willemsen		{
584*1c12ee1eSDan Willemsen			in: `1.020000`,
585*1c12ee1eSDan Willemsen			want: []R{
586*1c12ee1eSDan Willemsen				{V: F32{1.02}},
587*1c12ee1eSDan Willemsen				{V: EOF},
588*1c12ee1eSDan Willemsen			},
589*1c12ee1eSDan Willemsen		},
590*1c12ee1eSDan Willemsen		{
591*1c12ee1eSDan Willemsen			in: `-1.0e0`,
592*1c12ee1eSDan Willemsen			want: []R{
593*1c12ee1eSDan Willemsen				{V: F32{-1}},
594*1c12ee1eSDan Willemsen				{V: EOF},
595*1c12ee1eSDan Willemsen			},
596*1c12ee1eSDan Willemsen		},
597*1c12ee1eSDan Willemsen		{
598*1c12ee1eSDan Willemsen			in: `1.0e-000`,
599*1c12ee1eSDan Willemsen			want: []R{
600*1c12ee1eSDan Willemsen				{V: F32{1}},
601*1c12ee1eSDan Willemsen				{V: EOF},
602*1c12ee1eSDan Willemsen			},
603*1c12ee1eSDan Willemsen		},
604*1c12ee1eSDan Willemsen		{
605*1c12ee1eSDan Willemsen			in: `1e+00`,
606*1c12ee1eSDan Willemsen			want: []R{
607*1c12ee1eSDan Willemsen				{V: F32{1}},
608*1c12ee1eSDan Willemsen				{V: EOF},
609*1c12ee1eSDan Willemsen			},
610*1c12ee1eSDan Willemsen		},
611*1c12ee1eSDan Willemsen		{
612*1c12ee1eSDan Willemsen			in: `1.02e3`,
613*1c12ee1eSDan Willemsen			want: []R{
614*1c12ee1eSDan Willemsen				{V: F32{1.02e3}},
615*1c12ee1eSDan Willemsen				{V: EOF},
616*1c12ee1eSDan Willemsen			},
617*1c12ee1eSDan Willemsen		},
618*1c12ee1eSDan Willemsen		{
619*1c12ee1eSDan Willemsen			in: `-1.02E03`,
620*1c12ee1eSDan Willemsen			want: []R{
621*1c12ee1eSDan Willemsen				{V: F32{-1.02e3}},
622*1c12ee1eSDan Willemsen				{V: EOF},
623*1c12ee1eSDan Willemsen			},
624*1c12ee1eSDan Willemsen		},
625*1c12ee1eSDan Willemsen		{
626*1c12ee1eSDan Willemsen			in: `1.0200e+3`,
627*1c12ee1eSDan Willemsen			want: []R{
628*1c12ee1eSDan Willemsen				{V: F32{1.02e3}},
629*1c12ee1eSDan Willemsen				{V: EOF},
630*1c12ee1eSDan Willemsen			},
631*1c12ee1eSDan Willemsen		},
632*1c12ee1eSDan Willemsen		{
633*1c12ee1eSDan Willemsen			in: `-1.0200E+03`,
634*1c12ee1eSDan Willemsen			want: []R{
635*1c12ee1eSDan Willemsen				{V: F32{-1.02e3}},
636*1c12ee1eSDan Willemsen				{V: EOF},
637*1c12ee1eSDan Willemsen			},
638*1c12ee1eSDan Willemsen		},
639*1c12ee1eSDan Willemsen		{
640*1c12ee1eSDan Willemsen			in: `1.0200e-3`,
641*1c12ee1eSDan Willemsen			want: []R{
642*1c12ee1eSDan Willemsen				{V: F32{1.02e-3}},
643*1c12ee1eSDan Willemsen				{V: EOF},
644*1c12ee1eSDan Willemsen			},
645*1c12ee1eSDan Willemsen		},
646*1c12ee1eSDan Willemsen		{
647*1c12ee1eSDan Willemsen			in: `-1.0200E-03`,
648*1c12ee1eSDan Willemsen			want: []R{
649*1c12ee1eSDan Willemsen				{V: F32{-1.02e-3}},
650*1c12ee1eSDan Willemsen				{V: EOF},
651*1c12ee1eSDan Willemsen			},
652*1c12ee1eSDan Willemsen		},
653*1c12ee1eSDan Willemsen		{
654*1c12ee1eSDan Willemsen			// Exceeds max float32 limit, but should be ok for float64.
655*1c12ee1eSDan Willemsen			in: `3.4e39`,
656*1c12ee1eSDan Willemsen			want: []R{
657*1c12ee1eSDan Willemsen				{V: F64{3.4e39}},
658*1c12ee1eSDan Willemsen				{V: EOF},
659*1c12ee1eSDan Willemsen			},
660*1c12ee1eSDan Willemsen		},
661*1c12ee1eSDan Willemsen
662*1c12ee1eSDan Willemsen		{
663*1c12ee1eSDan Willemsen			// Exceeds max float32 limit.
664*1c12ee1eSDan Willemsen			in: `3.4e39`,
665*1c12ee1eSDan Willemsen			want: []R{
666*1c12ee1eSDan Willemsen				{V: NotF32},
667*1c12ee1eSDan Willemsen				{V: EOF},
668*1c12ee1eSDan Willemsen			},
669*1c12ee1eSDan Willemsen		},
670*1c12ee1eSDan Willemsen		{
671*1c12ee1eSDan Willemsen			// Less than negative max float32 limit.
672*1c12ee1eSDan Willemsen			in: `-3.4e39`,
673*1c12ee1eSDan Willemsen			want: []R{
674*1c12ee1eSDan Willemsen				{V: NotF32},
675*1c12ee1eSDan Willemsen				{V: EOF},
676*1c12ee1eSDan Willemsen			},
677*1c12ee1eSDan Willemsen		},
678*1c12ee1eSDan Willemsen		{
679*1c12ee1eSDan Willemsen			// Exceeds max float64 limit.
680*1c12ee1eSDan Willemsen			in: `1.79e+309`,
681*1c12ee1eSDan Willemsen			want: []R{
682*1c12ee1eSDan Willemsen				{V: NotF64},
683*1c12ee1eSDan Willemsen				{V: EOF},
684*1c12ee1eSDan Willemsen			},
685*1c12ee1eSDan Willemsen		},
686*1c12ee1eSDan Willemsen		{
687*1c12ee1eSDan Willemsen			// Less than negative max float64 limit.
688*1c12ee1eSDan Willemsen			in: `-1.79e+309`,
689*1c12ee1eSDan Willemsen			want: []R{
690*1c12ee1eSDan Willemsen				{V: NotF64},
691*1c12ee1eSDan Willemsen				{V: EOF},
692*1c12ee1eSDan Willemsen			},
693*1c12ee1eSDan Willemsen		},
694*1c12ee1eSDan Willemsen
695*1c12ee1eSDan Willemsen		// JSON numbers as signed integers.
696*1c12ee1eSDan Willemsen		{
697*1c12ee1eSDan Willemsen			in: space + `0` + space,
698*1c12ee1eSDan Willemsen			want: []R{
699*1c12ee1eSDan Willemsen				{V: I32{0}},
700*1c12ee1eSDan Willemsen				{V: EOF},
701*1c12ee1eSDan Willemsen			},
702*1c12ee1eSDan Willemsen		},
703*1c12ee1eSDan Willemsen		{
704*1c12ee1eSDan Willemsen			in: space + `-0` + space,
705*1c12ee1eSDan Willemsen			want: []R{
706*1c12ee1eSDan Willemsen				{V: I32{0}},
707*1c12ee1eSDan Willemsen				{V: EOF},
708*1c12ee1eSDan Willemsen			},
709*1c12ee1eSDan Willemsen		},
710*1c12ee1eSDan Willemsen		{
711*1c12ee1eSDan Willemsen			// Fractional part equals 0 is ok.
712*1c12ee1eSDan Willemsen			in: `1.00000`,
713*1c12ee1eSDan Willemsen			want: []R{
714*1c12ee1eSDan Willemsen				{V: I32{1}},
715*1c12ee1eSDan Willemsen				{V: EOF},
716*1c12ee1eSDan Willemsen			},
717*1c12ee1eSDan Willemsen		},
718*1c12ee1eSDan Willemsen		{
719*1c12ee1eSDan Willemsen			// Fractional part not equals 0 returns error.
720*1c12ee1eSDan Willemsen			in: `1.0000000001`,
721*1c12ee1eSDan Willemsen			want: []R{
722*1c12ee1eSDan Willemsen				{V: NotI32},
723*1c12ee1eSDan Willemsen				{V: EOF},
724*1c12ee1eSDan Willemsen			},
725*1c12ee1eSDan Willemsen		},
726*1c12ee1eSDan Willemsen		{
727*1c12ee1eSDan Willemsen			in: `0e0`,
728*1c12ee1eSDan Willemsen			want: []R{
729*1c12ee1eSDan Willemsen				{V: I32{0}},
730*1c12ee1eSDan Willemsen				{V: EOF},
731*1c12ee1eSDan Willemsen			},
732*1c12ee1eSDan Willemsen		},
733*1c12ee1eSDan Willemsen		{
734*1c12ee1eSDan Willemsen			in: `0.0E0`,
735*1c12ee1eSDan Willemsen			want: []R{
736*1c12ee1eSDan Willemsen				{V: I32{0}},
737*1c12ee1eSDan Willemsen				{V: EOF},
738*1c12ee1eSDan Willemsen			},
739*1c12ee1eSDan Willemsen		},
740*1c12ee1eSDan Willemsen		{
741*1c12ee1eSDan Willemsen			in: `0.0E10`,
742*1c12ee1eSDan Willemsen			want: []R{
743*1c12ee1eSDan Willemsen				{V: I32{0}},
744*1c12ee1eSDan Willemsen				{V: EOF},
745*1c12ee1eSDan Willemsen			},
746*1c12ee1eSDan Willemsen		},
747*1c12ee1eSDan Willemsen		{
748*1c12ee1eSDan Willemsen			in: `-1`,
749*1c12ee1eSDan Willemsen			want: []R{
750*1c12ee1eSDan Willemsen				{V: I32{-1}},
751*1c12ee1eSDan Willemsen				{V: EOF},
752*1c12ee1eSDan Willemsen			},
753*1c12ee1eSDan Willemsen		},
754*1c12ee1eSDan Willemsen		{
755*1c12ee1eSDan Willemsen			in: `1.0e+0`,
756*1c12ee1eSDan Willemsen			want: []R{
757*1c12ee1eSDan Willemsen				{V: I32{1}},
758*1c12ee1eSDan Willemsen				{V: EOF},
759*1c12ee1eSDan Willemsen			},
760*1c12ee1eSDan Willemsen		},
761*1c12ee1eSDan Willemsen		{
762*1c12ee1eSDan Willemsen			in: `-1E-0`,
763*1c12ee1eSDan Willemsen			want: []R{
764*1c12ee1eSDan Willemsen				{V: I32{-1}},
765*1c12ee1eSDan Willemsen				{V: EOF},
766*1c12ee1eSDan Willemsen			},
767*1c12ee1eSDan Willemsen		},
768*1c12ee1eSDan Willemsen		{
769*1c12ee1eSDan Willemsen			in: `1E1`,
770*1c12ee1eSDan Willemsen			want: []R{
771*1c12ee1eSDan Willemsen				{V: I32{10}},
772*1c12ee1eSDan Willemsen				{V: EOF},
773*1c12ee1eSDan Willemsen			},
774*1c12ee1eSDan Willemsen		},
775*1c12ee1eSDan Willemsen		{
776*1c12ee1eSDan Willemsen			in: `-100.00e-02`,
777*1c12ee1eSDan Willemsen			want: []R{
778*1c12ee1eSDan Willemsen				{V: I32{-1}},
779*1c12ee1eSDan Willemsen				{V: EOF},
780*1c12ee1eSDan Willemsen			},
781*1c12ee1eSDan Willemsen		},
782*1c12ee1eSDan Willemsen		{
783*1c12ee1eSDan Willemsen			in: `0.1200E+02`,
784*1c12ee1eSDan Willemsen			want: []R{
785*1c12ee1eSDan Willemsen				{V: I64{12}},
786*1c12ee1eSDan Willemsen				{V: EOF},
787*1c12ee1eSDan Willemsen			},
788*1c12ee1eSDan Willemsen		},
789*1c12ee1eSDan Willemsen		{
790*1c12ee1eSDan Willemsen			in: `0.012e2`,
791*1c12ee1eSDan Willemsen			want: []R{
792*1c12ee1eSDan Willemsen				{V: NotI32},
793*1c12ee1eSDan Willemsen				{V: EOF},
794*1c12ee1eSDan Willemsen			},
795*1c12ee1eSDan Willemsen		},
796*1c12ee1eSDan Willemsen		{
797*1c12ee1eSDan Willemsen			in: `12e-2`,
798*1c12ee1eSDan Willemsen			want: []R{
799*1c12ee1eSDan Willemsen				{V: NotI32},
800*1c12ee1eSDan Willemsen				{V: EOF},
801*1c12ee1eSDan Willemsen			},
802*1c12ee1eSDan Willemsen		},
803*1c12ee1eSDan Willemsen		{
804*1c12ee1eSDan Willemsen			// Exceeds math.MaxInt32.
805*1c12ee1eSDan Willemsen			in: `2147483648`,
806*1c12ee1eSDan Willemsen			want: []R{
807*1c12ee1eSDan Willemsen				{V: NotI32},
808*1c12ee1eSDan Willemsen				{V: EOF},
809*1c12ee1eSDan Willemsen			},
810*1c12ee1eSDan Willemsen		},
811*1c12ee1eSDan Willemsen		{
812*1c12ee1eSDan Willemsen			// Exceeds math.MinInt32.
813*1c12ee1eSDan Willemsen			in: `-2147483649`,
814*1c12ee1eSDan Willemsen			want: []R{
815*1c12ee1eSDan Willemsen				{V: NotI32},
816*1c12ee1eSDan Willemsen				{V: EOF},
817*1c12ee1eSDan Willemsen			},
818*1c12ee1eSDan Willemsen		},
819*1c12ee1eSDan Willemsen		{
820*1c12ee1eSDan Willemsen			// Exceeds math.MaxInt32, but ok for int64.
821*1c12ee1eSDan Willemsen			in: `2147483648`,
822*1c12ee1eSDan Willemsen			want: []R{
823*1c12ee1eSDan Willemsen				{V: I64{2147483648}},
824*1c12ee1eSDan Willemsen				{V: EOF},
825*1c12ee1eSDan Willemsen			},
826*1c12ee1eSDan Willemsen		},
827*1c12ee1eSDan Willemsen		{
828*1c12ee1eSDan Willemsen			// Exceeds math.MinInt32, but ok for int64.
829*1c12ee1eSDan Willemsen			in: `-2147483649`,
830*1c12ee1eSDan Willemsen			want: []R{
831*1c12ee1eSDan Willemsen				{V: I64{-2147483649}},
832*1c12ee1eSDan Willemsen				{V: EOF},
833*1c12ee1eSDan Willemsen			},
834*1c12ee1eSDan Willemsen		},
835*1c12ee1eSDan Willemsen		{
836*1c12ee1eSDan Willemsen			// Exceeds math.MaxInt64.
837*1c12ee1eSDan Willemsen			in: `9223372036854775808`,
838*1c12ee1eSDan Willemsen			want: []R{
839*1c12ee1eSDan Willemsen				{V: NotI64},
840*1c12ee1eSDan Willemsen				{V: EOF},
841*1c12ee1eSDan Willemsen			},
842*1c12ee1eSDan Willemsen		},
843*1c12ee1eSDan Willemsen		{
844*1c12ee1eSDan Willemsen			// Exceeds math.MinInt64.
845*1c12ee1eSDan Willemsen			in: `-9223372036854775809`,
846*1c12ee1eSDan Willemsen			want: []R{
847*1c12ee1eSDan Willemsen				{V: NotI64},
848*1c12ee1eSDan Willemsen				{V: EOF},
849*1c12ee1eSDan Willemsen			},
850*1c12ee1eSDan Willemsen		},
851*1c12ee1eSDan Willemsen
852*1c12ee1eSDan Willemsen		// JSON numbers as unsigned integers.
853*1c12ee1eSDan Willemsen		{
854*1c12ee1eSDan Willemsen			in: space + `0` + space,
855*1c12ee1eSDan Willemsen			want: []R{
856*1c12ee1eSDan Willemsen				{V: Ui32{0}},
857*1c12ee1eSDan Willemsen				{V: EOF},
858*1c12ee1eSDan Willemsen			},
859*1c12ee1eSDan Willemsen		},
860*1c12ee1eSDan Willemsen		{
861*1c12ee1eSDan Willemsen			in: space + `-0` + space,
862*1c12ee1eSDan Willemsen			want: []R{
863*1c12ee1eSDan Willemsen				{V: Ui32{0}},
864*1c12ee1eSDan Willemsen				{V: EOF},
865*1c12ee1eSDan Willemsen			},
866*1c12ee1eSDan Willemsen		},
867*1c12ee1eSDan Willemsen		{
868*1c12ee1eSDan Willemsen			in: `-1`,
869*1c12ee1eSDan Willemsen			want: []R{
870*1c12ee1eSDan Willemsen				{V: NotUi32},
871*1c12ee1eSDan Willemsen				{V: EOF},
872*1c12ee1eSDan Willemsen			},
873*1c12ee1eSDan Willemsen		},
874*1c12ee1eSDan Willemsen		{
875*1c12ee1eSDan Willemsen			// Exceeds math.MaxUint32.
876*1c12ee1eSDan Willemsen			in: `4294967296`,
877*1c12ee1eSDan Willemsen			want: []R{
878*1c12ee1eSDan Willemsen				{V: NotUi32},
879*1c12ee1eSDan Willemsen				{V: EOF},
880*1c12ee1eSDan Willemsen			},
881*1c12ee1eSDan Willemsen		},
882*1c12ee1eSDan Willemsen		{
883*1c12ee1eSDan Willemsen			// Exceeds math.MaxUint64.
884*1c12ee1eSDan Willemsen			in: `18446744073709551616`,
885*1c12ee1eSDan Willemsen			want: []R{
886*1c12ee1eSDan Willemsen				{V: NotUi64},
887*1c12ee1eSDan Willemsen				{V: EOF},
888*1c12ee1eSDan Willemsen			},
889*1c12ee1eSDan Willemsen		},
890*1c12ee1eSDan Willemsen
891*1c12ee1eSDan Willemsen		// JSON sequence of values.
892*1c12ee1eSDan Willemsen		{
893*1c12ee1eSDan Willemsen			in: `true null`,
894*1c12ee1eSDan Willemsen			want: []R{
895*1c12ee1eSDan Willemsen				{V: Bool{true}},
896*1c12ee1eSDan Willemsen				{E: `(line 1:6): unexpected token null`},
897*1c12ee1eSDan Willemsen			},
898*1c12ee1eSDan Willemsen		},
899*1c12ee1eSDan Willemsen		{
900*1c12ee1eSDan Willemsen			in: "null false",
901*1c12ee1eSDan Willemsen			want: []R{
902*1c12ee1eSDan Willemsen				{V: Null},
903*1c12ee1eSDan Willemsen				{E: `unexpected token false`},
904*1c12ee1eSDan Willemsen			},
905*1c12ee1eSDan Willemsen		},
906*1c12ee1eSDan Willemsen		{
907*1c12ee1eSDan Willemsen			in: `true,false`,
908*1c12ee1eSDan Willemsen			want: []R{
909*1c12ee1eSDan Willemsen				{V: Bool{true}},
910*1c12ee1eSDan Willemsen				{E: `unexpected token ,`},
911*1c12ee1eSDan Willemsen			},
912*1c12ee1eSDan Willemsen		},
913*1c12ee1eSDan Willemsen		{
914*1c12ee1eSDan Willemsen			in: `47"hello"`,
915*1c12ee1eSDan Willemsen			want: []R{
916*1c12ee1eSDan Willemsen				{V: I32{47}},
917*1c12ee1eSDan Willemsen				{E: `unexpected token "hello"`},
918*1c12ee1eSDan Willemsen			},
919*1c12ee1eSDan Willemsen		},
920*1c12ee1eSDan Willemsen		{
921*1c12ee1eSDan Willemsen			in: `47 "hello"`,
922*1c12ee1eSDan Willemsen			want: []R{
923*1c12ee1eSDan Willemsen				{V: I32{47}},
924*1c12ee1eSDan Willemsen				{E: `unexpected token "hello"`},
925*1c12ee1eSDan Willemsen			},
926*1c12ee1eSDan Willemsen		},
927*1c12ee1eSDan Willemsen		{
928*1c12ee1eSDan Willemsen			in: `true 42`,
929*1c12ee1eSDan Willemsen			want: []R{
930*1c12ee1eSDan Willemsen				{V: Bool{true}},
931*1c12ee1eSDan Willemsen				{E: `unexpected token 42`},
932*1c12ee1eSDan Willemsen			},
933*1c12ee1eSDan Willemsen		},
934*1c12ee1eSDan Willemsen
935*1c12ee1eSDan Willemsen		// JSON arrays.
936*1c12ee1eSDan Willemsen		{
937*1c12ee1eSDan Willemsen			in: space + `[]` + space,
938*1c12ee1eSDan Willemsen			want: []R{
939*1c12ee1eSDan Willemsen				{V: ArrayOpen},
940*1c12ee1eSDan Willemsen				{V: ArrayClose},
941*1c12ee1eSDan Willemsen				{V: EOF},
942*1c12ee1eSDan Willemsen			},
943*1c12ee1eSDan Willemsen		},
944*1c12ee1eSDan Willemsen		{
945*1c12ee1eSDan Willemsen			in: space + `[` + space + `]` + space,
946*1c12ee1eSDan Willemsen			want: []R{
947*1c12ee1eSDan Willemsen				{V: ArrayOpen, P: len(space), RS: `[`},
948*1c12ee1eSDan Willemsen				{V: ArrayClose},
949*1c12ee1eSDan Willemsen				{V: EOF},
950*1c12ee1eSDan Willemsen			},
951*1c12ee1eSDan Willemsen		},
952*1c12ee1eSDan Willemsen		{
953*1c12ee1eSDan Willemsen			in: space + `[` + space,
954*1c12ee1eSDan Willemsen			want: []R{
955*1c12ee1eSDan Willemsen				{V: ArrayOpen},
956*1c12ee1eSDan Willemsen				{E: errEOF},
957*1c12ee1eSDan Willemsen			},
958*1c12ee1eSDan Willemsen		},
959*1c12ee1eSDan Willemsen		{
960*1c12ee1eSDan Willemsen			in:   space + `]` + space,
961*1c12ee1eSDan Willemsen			want: []R{{E: `unexpected token ]`}},
962*1c12ee1eSDan Willemsen		},
963*1c12ee1eSDan Willemsen		{
964*1c12ee1eSDan Willemsen			in: `[null,true,false,  1e1, "hello"   ]`,
965*1c12ee1eSDan Willemsen			want: []R{
966*1c12ee1eSDan Willemsen				{V: ArrayOpen},
967*1c12ee1eSDan Willemsen				{V: Null},
968*1c12ee1eSDan Willemsen				{V: Bool{true}},
969*1c12ee1eSDan Willemsen				{V: Bool{false}},
970*1c12ee1eSDan Willemsen				{V: I32{10}},
971*1c12ee1eSDan Willemsen				{V: Str{"hello"}},
972*1c12ee1eSDan Willemsen				{V: ArrayClose},
973*1c12ee1eSDan Willemsen				{V: EOF},
974*1c12ee1eSDan Willemsen			},
975*1c12ee1eSDan Willemsen		},
976*1c12ee1eSDan Willemsen		{
977*1c12ee1eSDan Willemsen			in: `[` + space + `true` + space + `,` + space + `"hello"` + space + `]`,
978*1c12ee1eSDan Willemsen			want: []R{
979*1c12ee1eSDan Willemsen				{V: ArrayOpen},
980*1c12ee1eSDan Willemsen				{V: Bool{true}},
981*1c12ee1eSDan Willemsen				{V: Str{"hello"}},
982*1c12ee1eSDan Willemsen				{V: ArrayClose},
983*1c12ee1eSDan Willemsen				{V: EOF},
984*1c12ee1eSDan Willemsen			},
985*1c12ee1eSDan Willemsen		},
986*1c12ee1eSDan Willemsen		{
987*1c12ee1eSDan Willemsen			in: `[` + space + `true` + space + `,` + space + `]`,
988*1c12ee1eSDan Willemsen			want: []R{
989*1c12ee1eSDan Willemsen				{V: ArrayOpen},
990*1c12ee1eSDan Willemsen				{V: Bool{true}},
991*1c12ee1eSDan Willemsen				{E: `unexpected token ]`},
992*1c12ee1eSDan Willemsen			},
993*1c12ee1eSDan Willemsen		},
994*1c12ee1eSDan Willemsen		{
995*1c12ee1eSDan Willemsen			in: `[` + space + `false` + space + `]`,
996*1c12ee1eSDan Willemsen			want: []R{
997*1c12ee1eSDan Willemsen				{V: ArrayOpen},
998*1c12ee1eSDan Willemsen				{V: Bool{false}},
999*1c12ee1eSDan Willemsen				{V: ArrayClose},
1000*1c12ee1eSDan Willemsen				{V: EOF},
1001*1c12ee1eSDan Willemsen			},
1002*1c12ee1eSDan Willemsen		},
1003*1c12ee1eSDan Willemsen		{
1004*1c12ee1eSDan Willemsen			in: `[` + space + `1` + space + `0` + space + `]`,
1005*1c12ee1eSDan Willemsen			want: []R{
1006*1c12ee1eSDan Willemsen				{V: ArrayOpen},
1007*1c12ee1eSDan Willemsen				{V: I64{1}},
1008*1c12ee1eSDan Willemsen				{E: `unexpected token 0`},
1009*1c12ee1eSDan Willemsen			},
1010*1c12ee1eSDan Willemsen		},
1011*1c12ee1eSDan Willemsen		{
1012*1c12ee1eSDan Willemsen			in: `[null`,
1013*1c12ee1eSDan Willemsen			want: []R{
1014*1c12ee1eSDan Willemsen				{V: ArrayOpen},
1015*1c12ee1eSDan Willemsen				{V: Null},
1016*1c12ee1eSDan Willemsen				{E: errEOF},
1017*1c12ee1eSDan Willemsen			},
1018*1c12ee1eSDan Willemsen		},
1019*1c12ee1eSDan Willemsen		{
1020*1c12ee1eSDan Willemsen			in: `[foo]`,
1021*1c12ee1eSDan Willemsen			want: []R{
1022*1c12ee1eSDan Willemsen				{V: ArrayOpen},
1023*1c12ee1eSDan Willemsen				{E: `invalid value foo`},
1024*1c12ee1eSDan Willemsen			},
1025*1c12ee1eSDan Willemsen		},
1026*1c12ee1eSDan Willemsen		{
1027*1c12ee1eSDan Willemsen			in: `[{}, "hello", [true, false], null]`,
1028*1c12ee1eSDan Willemsen			want: []R{
1029*1c12ee1eSDan Willemsen				{V: ArrayOpen},
1030*1c12ee1eSDan Willemsen				{V: ObjectOpen},
1031*1c12ee1eSDan Willemsen				{V: ObjectClose},
1032*1c12ee1eSDan Willemsen				{V: Str{"hello"}},
1033*1c12ee1eSDan Willemsen				{V: ArrayOpen},
1034*1c12ee1eSDan Willemsen				{V: Bool{true}},
1035*1c12ee1eSDan Willemsen				{V: Bool{false}},
1036*1c12ee1eSDan Willemsen				{V: ArrayClose},
1037*1c12ee1eSDan Willemsen				{V: Null},
1038*1c12ee1eSDan Willemsen				{V: ArrayClose},
1039*1c12ee1eSDan Willemsen				{V: EOF},
1040*1c12ee1eSDan Willemsen			},
1041*1c12ee1eSDan Willemsen		},
1042*1c12ee1eSDan Willemsen		{
1043*1c12ee1eSDan Willemsen			in: `[{ ]`,
1044*1c12ee1eSDan Willemsen			want: []R{
1045*1c12ee1eSDan Willemsen				{V: ArrayOpen},
1046*1c12ee1eSDan Willemsen				{V: ObjectOpen},
1047*1c12ee1eSDan Willemsen				{E: `unexpected token ]`},
1048*1c12ee1eSDan Willemsen			},
1049*1c12ee1eSDan Willemsen		},
1050*1c12ee1eSDan Willemsen		{
1051*1c12ee1eSDan Willemsen			in: `[[ ]`,
1052*1c12ee1eSDan Willemsen			want: []R{
1053*1c12ee1eSDan Willemsen				{V: ArrayOpen},
1054*1c12ee1eSDan Willemsen				{V: ArrayOpen},
1055*1c12ee1eSDan Willemsen				{V: ArrayClose},
1056*1c12ee1eSDan Willemsen				{E: errEOF},
1057*1c12ee1eSDan Willemsen			},
1058*1c12ee1eSDan Willemsen		},
1059*1c12ee1eSDan Willemsen		{
1060*1c12ee1eSDan Willemsen			in: `[,]`,
1061*1c12ee1eSDan Willemsen			want: []R{
1062*1c12ee1eSDan Willemsen				{V: ArrayOpen},
1063*1c12ee1eSDan Willemsen				{E: `unexpected token ,`},
1064*1c12ee1eSDan Willemsen			},
1065*1c12ee1eSDan Willemsen		},
1066*1c12ee1eSDan Willemsen		{
1067*1c12ee1eSDan Willemsen			in: `[true "hello"]`,
1068*1c12ee1eSDan Willemsen			want: []R{
1069*1c12ee1eSDan Willemsen				{V: ArrayOpen},
1070*1c12ee1eSDan Willemsen				{V: Bool{true}},
1071*1c12ee1eSDan Willemsen				{E: `unexpected token "hello"`},
1072*1c12ee1eSDan Willemsen			},
1073*1c12ee1eSDan Willemsen		},
1074*1c12ee1eSDan Willemsen		{
1075*1c12ee1eSDan Willemsen			in: `[] null`,
1076*1c12ee1eSDan Willemsen			want: []R{
1077*1c12ee1eSDan Willemsen				{V: ArrayOpen},
1078*1c12ee1eSDan Willemsen				{V: ArrayClose},
1079*1c12ee1eSDan Willemsen				{E: `unexpected token null`},
1080*1c12ee1eSDan Willemsen			},
1081*1c12ee1eSDan Willemsen		},
1082*1c12ee1eSDan Willemsen		{
1083*1c12ee1eSDan Willemsen			in: `true []`,
1084*1c12ee1eSDan Willemsen			want: []R{
1085*1c12ee1eSDan Willemsen				{V: Bool{true}},
1086*1c12ee1eSDan Willemsen				{E: `unexpected token [`},
1087*1c12ee1eSDan Willemsen			},
1088*1c12ee1eSDan Willemsen		},
1089*1c12ee1eSDan Willemsen
1090*1c12ee1eSDan Willemsen		// JSON objects.
1091*1c12ee1eSDan Willemsen		{
1092*1c12ee1eSDan Willemsen			in: space + `{}` + space,
1093*1c12ee1eSDan Willemsen			want: []R{
1094*1c12ee1eSDan Willemsen				{V: ObjectOpen},
1095*1c12ee1eSDan Willemsen				{V: ObjectClose},
1096*1c12ee1eSDan Willemsen				{V: EOF},
1097*1c12ee1eSDan Willemsen			},
1098*1c12ee1eSDan Willemsen		},
1099*1c12ee1eSDan Willemsen		{
1100*1c12ee1eSDan Willemsen			in: space + `{` + space + `}` + space,
1101*1c12ee1eSDan Willemsen			want: []R{
1102*1c12ee1eSDan Willemsen				{V: ObjectOpen},
1103*1c12ee1eSDan Willemsen				{V: ObjectClose},
1104*1c12ee1eSDan Willemsen				{V: EOF},
1105*1c12ee1eSDan Willemsen			},
1106*1c12ee1eSDan Willemsen		},
1107*1c12ee1eSDan Willemsen		{
1108*1c12ee1eSDan Willemsen			in: space + `{` + space,
1109*1c12ee1eSDan Willemsen			want: []R{
1110*1c12ee1eSDan Willemsen				{V: ObjectOpen},
1111*1c12ee1eSDan Willemsen				{E: errEOF},
1112*1c12ee1eSDan Willemsen			},
1113*1c12ee1eSDan Willemsen		},
1114*1c12ee1eSDan Willemsen		{
1115*1c12ee1eSDan Willemsen			in:   space + `}` + space,
1116*1c12ee1eSDan Willemsen			want: []R{{E: `unexpected token }`}},
1117*1c12ee1eSDan Willemsen		},
1118*1c12ee1eSDan Willemsen		{
1119*1c12ee1eSDan Willemsen			in: `{` + space + `null` + space + `}`,
1120*1c12ee1eSDan Willemsen			want: []R{
1121*1c12ee1eSDan Willemsen				{V: ObjectOpen},
1122*1c12ee1eSDan Willemsen				{E: `unexpected token null`},
1123*1c12ee1eSDan Willemsen			},
1124*1c12ee1eSDan Willemsen		},
1125*1c12ee1eSDan Willemsen		{
1126*1c12ee1eSDan Willemsen			in: `{[]}`,
1127*1c12ee1eSDan Willemsen			want: []R{
1128*1c12ee1eSDan Willemsen				{V: ObjectOpen},
1129*1c12ee1eSDan Willemsen				{E: `(line 1:2): unexpected token [`},
1130*1c12ee1eSDan Willemsen			},
1131*1c12ee1eSDan Willemsen		},
1132*1c12ee1eSDan Willemsen		{
1133*1c12ee1eSDan Willemsen			in: `{,}`,
1134*1c12ee1eSDan Willemsen			want: []R{
1135*1c12ee1eSDan Willemsen				{V: ObjectOpen},
1136*1c12ee1eSDan Willemsen				{E: `unexpected token ,`},
1137*1c12ee1eSDan Willemsen			},
1138*1c12ee1eSDan Willemsen		},
1139*1c12ee1eSDan Willemsen		{
1140*1c12ee1eSDan Willemsen			in: `{"345678"}`,
1141*1c12ee1eSDan Willemsen			want: []R{
1142*1c12ee1eSDan Willemsen				{V: ObjectOpen},
1143*1c12ee1eSDan Willemsen				{E: `(line 1:10): unexpected character }, missing ":" after field name`},
1144*1c12ee1eSDan Willemsen			},
1145*1c12ee1eSDan Willemsen		},
1146*1c12ee1eSDan Willemsen		{
1147*1c12ee1eSDan Willemsen			in: `{` + space + `"hello"` + space + `:` + space + `"world"` + space + `}`,
1148*1c12ee1eSDan Willemsen			want: []R{
1149*1c12ee1eSDan Willemsen				{V: ObjectOpen},
1150*1c12ee1eSDan Willemsen				{V: Name{"hello"}, P: len(space) + 1, RS: `"hello"`},
1151*1c12ee1eSDan Willemsen				{V: Str{"world"}, RS: `"world"`},
1152*1c12ee1eSDan Willemsen				{V: ObjectClose},
1153*1c12ee1eSDan Willemsen				{V: EOF},
1154*1c12ee1eSDan Willemsen			},
1155*1c12ee1eSDan Willemsen		},
1156*1c12ee1eSDan Willemsen		{
1157*1c12ee1eSDan Willemsen			in: `{"hello" "world"}`,
1158*1c12ee1eSDan Willemsen			want: []R{
1159*1c12ee1eSDan Willemsen				{V: ObjectOpen},
1160*1c12ee1eSDan Willemsen				{E: `(line 1:10): unexpected character ", missing ":" after field name`},
1161*1c12ee1eSDan Willemsen			},
1162*1c12ee1eSDan Willemsen		},
1163*1c12ee1eSDan Willemsen		{
1164*1c12ee1eSDan Willemsen			in: `{"hello":`,
1165*1c12ee1eSDan Willemsen			want: []R{
1166*1c12ee1eSDan Willemsen				{V: ObjectOpen},
1167*1c12ee1eSDan Willemsen				{V: Name{"hello"}},
1168*1c12ee1eSDan Willemsen				{E: errEOF},
1169*1c12ee1eSDan Willemsen			},
1170*1c12ee1eSDan Willemsen		},
1171*1c12ee1eSDan Willemsen		{
1172*1c12ee1eSDan Willemsen			in: `{"hello":"world"`,
1173*1c12ee1eSDan Willemsen			want: []R{
1174*1c12ee1eSDan Willemsen				{V: ObjectOpen},
1175*1c12ee1eSDan Willemsen				{V: Name{"hello"}},
1176*1c12ee1eSDan Willemsen				{V: Str{"world"}},
1177*1c12ee1eSDan Willemsen				{E: errEOF},
1178*1c12ee1eSDan Willemsen			},
1179*1c12ee1eSDan Willemsen		},
1180*1c12ee1eSDan Willemsen		{
1181*1c12ee1eSDan Willemsen			in: `{"hello":"world",`,
1182*1c12ee1eSDan Willemsen			want: []R{
1183*1c12ee1eSDan Willemsen				{V: ObjectOpen},
1184*1c12ee1eSDan Willemsen				{V: Name{"hello"}},
1185*1c12ee1eSDan Willemsen				{V: Str{"world"}},
1186*1c12ee1eSDan Willemsen				{E: errEOF},
1187*1c12ee1eSDan Willemsen			},
1188*1c12ee1eSDan Willemsen		},
1189*1c12ee1eSDan Willemsen		{
1190*1c12ee1eSDan Willemsen			in: `{""`,
1191*1c12ee1eSDan Willemsen			want: []R{
1192*1c12ee1eSDan Willemsen				{V: ObjectOpen},
1193*1c12ee1eSDan Willemsen				{E: errEOF},
1194*1c12ee1eSDan Willemsen			},
1195*1c12ee1eSDan Willemsen		},
1196*1c12ee1eSDan Willemsen		{
1197*1c12ee1eSDan Willemsen			in: `{"34":"89",}`,
1198*1c12ee1eSDan Willemsen			want: []R{
1199*1c12ee1eSDan Willemsen				{V: ObjectOpen},
1200*1c12ee1eSDan Willemsen				{V: Name{"34"}, RS: `"34"`},
1201*1c12ee1eSDan Willemsen				{V: Str{"89"}},
1202*1c12ee1eSDan Willemsen				{E: `syntax error (line 1:12): unexpected token }`},
1203*1c12ee1eSDan Willemsen			},
1204*1c12ee1eSDan Willemsen		},
1205*1c12ee1eSDan Willemsen		{
1206*1c12ee1eSDan Willemsen			in: `{
1207*1c12ee1eSDan Willemsen			  "number": 123e2,
1208*1c12ee1eSDan Willemsen			  "bool"  : false,
1209*1c12ee1eSDan Willemsen			  "object": {"string": "world"},
1210*1c12ee1eSDan Willemsen			  "null"  : null,
1211*1c12ee1eSDan Willemsen			  "array" : [1.01, "hello", true],
1212*1c12ee1eSDan Willemsen			  "string": "hello"
1213*1c12ee1eSDan Willemsen			}`,
1214*1c12ee1eSDan Willemsen			want: []R{
1215*1c12ee1eSDan Willemsen				{V: ObjectOpen},
1216*1c12ee1eSDan Willemsen
1217*1c12ee1eSDan Willemsen				{V: Name{"number"}},
1218*1c12ee1eSDan Willemsen				{V: I32{12300}},
1219*1c12ee1eSDan Willemsen
1220*1c12ee1eSDan Willemsen				{V: Name{"bool"}},
1221*1c12ee1eSDan Willemsen				{V: Bool{false}},
1222*1c12ee1eSDan Willemsen
1223*1c12ee1eSDan Willemsen				{V: Name{"object"}},
1224*1c12ee1eSDan Willemsen				{V: ObjectOpen},
1225*1c12ee1eSDan Willemsen				{V: Name{"string"}},
1226*1c12ee1eSDan Willemsen				{V: Str{"world"}},
1227*1c12ee1eSDan Willemsen				{V: ObjectClose},
1228*1c12ee1eSDan Willemsen
1229*1c12ee1eSDan Willemsen				{V: Name{"null"}},
1230*1c12ee1eSDan Willemsen				{V: Null},
1231*1c12ee1eSDan Willemsen
1232*1c12ee1eSDan Willemsen				{V: Name{"array"}},
1233*1c12ee1eSDan Willemsen				{V: ArrayOpen},
1234*1c12ee1eSDan Willemsen				{V: F32{1.01}},
1235*1c12ee1eSDan Willemsen				{V: Str{"hello"}},
1236*1c12ee1eSDan Willemsen				{V: Bool{true}},
1237*1c12ee1eSDan Willemsen				{V: ArrayClose},
1238*1c12ee1eSDan Willemsen
1239*1c12ee1eSDan Willemsen				{V: Name{"string"}},
1240*1c12ee1eSDan Willemsen				{V: Str{"hello"}},
1241*1c12ee1eSDan Willemsen
1242*1c12ee1eSDan Willemsen				{V: ObjectClose},
1243*1c12ee1eSDan Willemsen				{V: EOF},
1244*1c12ee1eSDan Willemsen			},
1245*1c12ee1eSDan Willemsen		},
1246*1c12ee1eSDan Willemsen		{
1247*1c12ee1eSDan Willemsen			in: `[
1248*1c12ee1eSDan Willemsen			  {"object": {"number": 47}},
1249*1c12ee1eSDan Willemsen			  ["list"],
1250*1c12ee1eSDan Willemsen			  null
1251*1c12ee1eSDan Willemsen			]`,
1252*1c12ee1eSDan Willemsen			want: []R{
1253*1c12ee1eSDan Willemsen				{V: ArrayOpen},
1254*1c12ee1eSDan Willemsen
1255*1c12ee1eSDan Willemsen				{V: ObjectOpen},
1256*1c12ee1eSDan Willemsen				{V: Name{"object"}},
1257*1c12ee1eSDan Willemsen				{V: ObjectOpen},
1258*1c12ee1eSDan Willemsen				{V: Name{"number"}},
1259*1c12ee1eSDan Willemsen				{V: I32{47}},
1260*1c12ee1eSDan Willemsen				{V: ObjectClose},
1261*1c12ee1eSDan Willemsen				{V: ObjectClose},
1262*1c12ee1eSDan Willemsen
1263*1c12ee1eSDan Willemsen				{V: ArrayOpen},
1264*1c12ee1eSDan Willemsen				{V: Str{"list"}},
1265*1c12ee1eSDan Willemsen				{V: ArrayClose},
1266*1c12ee1eSDan Willemsen
1267*1c12ee1eSDan Willemsen				{V: Null},
1268*1c12ee1eSDan Willemsen
1269*1c12ee1eSDan Willemsen				{V: ArrayClose},
1270*1c12ee1eSDan Willemsen				{V: EOF},
1271*1c12ee1eSDan Willemsen			},
1272*1c12ee1eSDan Willemsen		},
1273*1c12ee1eSDan Willemsen
1274*1c12ee1eSDan Willemsen		// Tests for line and column info.
1275*1c12ee1eSDan Willemsen		{
1276*1c12ee1eSDan Willemsen			in: `12345678 x`,
1277*1c12ee1eSDan Willemsen			want: []R{
1278*1c12ee1eSDan Willemsen				{V: I64{12345678}},
1279*1c12ee1eSDan Willemsen				{E: `syntax error (line 1:10): invalid value x`},
1280*1c12ee1eSDan Willemsen			},
1281*1c12ee1eSDan Willemsen		},
1282*1c12ee1eSDan Willemsen		{
1283*1c12ee1eSDan Willemsen			in: "\ntrue\n   x",
1284*1c12ee1eSDan Willemsen			want: []R{
1285*1c12ee1eSDan Willemsen				{V: Bool{true}},
1286*1c12ee1eSDan Willemsen				{E: `syntax error (line 3:4): invalid value x`},
1287*1c12ee1eSDan Willemsen			},
1288*1c12ee1eSDan Willemsen		},
1289*1c12ee1eSDan Willemsen		{
1290*1c12ee1eSDan Willemsen			in: `"��"x`,
1291*1c12ee1eSDan Willemsen			want: []R{
1292*1c12ee1eSDan Willemsen				{V: Str{"��"}},
1293*1c12ee1eSDan Willemsen				{E: `syntax error (line 1:4): invalid value x`},
1294*1c12ee1eSDan Willemsen			},
1295*1c12ee1eSDan Willemsen		},
1296*1c12ee1eSDan Willemsen		{
1297*1c12ee1eSDan Willemsen			in: "\n\n[\"������\"x",
1298*1c12ee1eSDan Willemsen			want: []R{
1299*1c12ee1eSDan Willemsen				{V: ArrayOpen},
1300*1c12ee1eSDan Willemsen				{V: Str{"������"}},
1301*1c12ee1eSDan Willemsen				{E: `syntax error (line 3:7): invalid value x`},
1302*1c12ee1eSDan Willemsen			},
1303*1c12ee1eSDan Willemsen		},
1304*1c12ee1eSDan Willemsen		{
1305*1c12ee1eSDan Willemsen			// Multi-rune emojis.
1306*1c12ee1eSDan Willemsen			in: `["��������"x`,
1307*1c12ee1eSDan Willemsen			want: []R{
1308*1c12ee1eSDan Willemsen				{V: ArrayOpen},
1309*1c12ee1eSDan Willemsen				{V: Str{"��������"}},
1310*1c12ee1eSDan Willemsen				{E: `syntax error (line 1:8): invalid value x`},
1311*1c12ee1eSDan Willemsen			},
1312*1c12ee1eSDan Willemsen		},
1313*1c12ee1eSDan Willemsen	}
1314*1c12ee1eSDan Willemsen
1315*1c12ee1eSDan Willemsen	for _, tc := range tests {
1316*1c12ee1eSDan Willemsen		tc := tc
1317*1c12ee1eSDan Willemsen		t.Run("", func(t *testing.T) {
1318*1c12ee1eSDan Willemsen			dec := json.NewDecoder([]byte(tc.in))
1319*1c12ee1eSDan Willemsen			for i, want := range tc.want {
1320*1c12ee1eSDan Willemsen				peekTok, peekErr := dec.Peek()
1321*1c12ee1eSDan Willemsen				tok, err := dec.Read()
1322*1c12ee1eSDan Willemsen				if err != nil {
1323*1c12ee1eSDan Willemsen					if want.E == "" {
1324*1c12ee1eSDan Willemsen						errorf(t, tc.in, "want#%d: Read() got unexpected error: %v", i, err)
1325*1c12ee1eSDan Willemsen					} else if !strings.Contains(err.Error(), want.E) {
1326*1c12ee1eSDan Willemsen						errorf(t, tc.in, "want#%d: Read() got %q, want %q", i, err, want.E)
1327*1c12ee1eSDan Willemsen					}
1328*1c12ee1eSDan Willemsen					return
1329*1c12ee1eSDan Willemsen				}
1330*1c12ee1eSDan Willemsen				if want.E != "" {
1331*1c12ee1eSDan Willemsen					errorf(t, tc.in, "want#%d: Read() got nil error, want %q", i, want.E)
1332*1c12ee1eSDan Willemsen					return
1333*1c12ee1eSDan Willemsen				}
1334*1c12ee1eSDan Willemsen				checkToken(t, tok, i, want, tc.in)
1335*1c12ee1eSDan Willemsen				if !cmp.Equal(tok, peekTok, cmp.Comparer(json.TokenEquals)) {
1336*1c12ee1eSDan Willemsen					errorf(t, tc.in, "want#%d: Peek() %+v != Read() token %+v", i, peekTok, tok)
1337*1c12ee1eSDan Willemsen				}
1338*1c12ee1eSDan Willemsen				if err != peekErr {
1339*1c12ee1eSDan Willemsen					errorf(t, tc.in, "want#%d: Peek() error %v != Read() error %v", i, err, peekErr)
1340*1c12ee1eSDan Willemsen				}
1341*1c12ee1eSDan Willemsen			}
1342*1c12ee1eSDan Willemsen		})
1343*1c12ee1eSDan Willemsen	}
1344*1c12ee1eSDan Willemsen}
1345*1c12ee1eSDan Willemsen
1346*1c12ee1eSDan Willemsenfunc checkToken(t *testing.T, tok json.Token, idx int, r R, in string) {
1347*1c12ee1eSDan Willemsen	// Validate Token.Pos() if R.P is set.
1348*1c12ee1eSDan Willemsen	if r.P > 0 {
1349*1c12ee1eSDan Willemsen		got := tok.Pos()
1350*1c12ee1eSDan Willemsen		if got != r.P {
1351*1c12ee1eSDan Willemsen			errorf(t, in, "want#%d: Token.Pos() got %v want %v", idx, got, r.P)
1352*1c12ee1eSDan Willemsen		}
1353*1c12ee1eSDan Willemsen	}
1354*1c12ee1eSDan Willemsen	// Validate Token.RawString if R.RS is set.
1355*1c12ee1eSDan Willemsen	if len(r.RS) > 0 {
1356*1c12ee1eSDan Willemsen		got := tok.RawString()
1357*1c12ee1eSDan Willemsen		if got != r.RS {
1358*1c12ee1eSDan Willemsen			errorf(t, in, "want#%d: Token.RawString() got %v want %v", idx, got, r.P)
1359*1c12ee1eSDan Willemsen		}
1360*1c12ee1eSDan Willemsen	}
1361*1c12ee1eSDan Willemsen
1362*1c12ee1eSDan Willemsen	// Skip checking for Token details if r.V is not set.
1363*1c12ee1eSDan Willemsen	if r.V == nil {
1364*1c12ee1eSDan Willemsen		return
1365*1c12ee1eSDan Willemsen	}
1366*1c12ee1eSDan Willemsen
1367*1c12ee1eSDan Willemsen	if err := r.V.check(tok); err != "" {
1368*1c12ee1eSDan Willemsen		errorf(t, in, "want#%d: %s", idx, err)
1369*1c12ee1eSDan Willemsen	}
1370*1c12ee1eSDan Willemsen	return
1371*1c12ee1eSDan Willemsen}
1372*1c12ee1eSDan Willemsen
1373*1c12ee1eSDan Willemsenfunc errorf(t *testing.T, in string, fmtStr string, args ...interface{}) {
1374*1c12ee1eSDan Willemsen	t.Helper()
1375*1c12ee1eSDan Willemsen	vargs := []interface{}{in}
1376*1c12ee1eSDan Willemsen	for _, arg := range args {
1377*1c12ee1eSDan Willemsen		vargs = append(vargs, arg)
1378*1c12ee1eSDan Willemsen	}
1379*1c12ee1eSDan Willemsen	t.Errorf("input:\n%s\n~end~\n"+fmtStr, vargs...)
1380*1c12ee1eSDan Willemsen}
1381*1c12ee1eSDan Willemsen
1382*1c12ee1eSDan Willemsenfunc TestClone(t *testing.T) {
1383*1c12ee1eSDan Willemsen	input := `{"outer":{"str":"hello", "number": 123}}`
1384*1c12ee1eSDan Willemsen	dec := json.NewDecoder([]byte(input))
1385*1c12ee1eSDan Willemsen
1386*1c12ee1eSDan Willemsen	// Clone at the start should produce the same reads as the original.
1387*1c12ee1eSDan Willemsen	clone := dec.Clone()
1388*1c12ee1eSDan Willemsen	compareDecoders(t, dec, clone)
1389*1c12ee1eSDan Willemsen
1390*1c12ee1eSDan Willemsen	// Advance to inner object, clone and compare again.
1391*1c12ee1eSDan Willemsen	dec.Read() // Read ObjectOpen.
1392*1c12ee1eSDan Willemsen	dec.Read() // Read Name.
1393*1c12ee1eSDan Willemsen	clone = dec.Clone()
1394*1c12ee1eSDan Willemsen	compareDecoders(t, dec, clone)
1395*1c12ee1eSDan Willemsen}
1396*1c12ee1eSDan Willemsen
1397*1c12ee1eSDan Willemsenfunc compareDecoders(t *testing.T, d1 *json.Decoder, d2 *json.Decoder) {
1398*1c12ee1eSDan Willemsen	for {
1399*1c12ee1eSDan Willemsen		tok1, err1 := d1.Read()
1400*1c12ee1eSDan Willemsen		tok2, err2 := d2.Read()
1401*1c12ee1eSDan Willemsen		if tok1.Kind() != tok2.Kind() {
1402*1c12ee1eSDan Willemsen			t.Errorf("cloned decoder: got Kind %v, want %v", tok2.Kind(), tok1.Kind())
1403*1c12ee1eSDan Willemsen		}
1404*1c12ee1eSDan Willemsen		if tok1.RawString() != tok2.RawString() {
1405*1c12ee1eSDan Willemsen			t.Errorf("cloned decoder: got RawString %v, want %v", tok2.RawString(), tok1.RawString())
1406*1c12ee1eSDan Willemsen		}
1407*1c12ee1eSDan Willemsen		if err1 != err2 {
1408*1c12ee1eSDan Willemsen			t.Errorf("cloned decoder: got error %v, want %v", err2, err1)
1409*1c12ee1eSDan Willemsen		}
1410*1c12ee1eSDan Willemsen		if tok1.Kind() == json.EOF {
1411*1c12ee1eSDan Willemsen			break
1412*1c12ee1eSDan Willemsen		}
1413*1c12ee1eSDan Willemsen	}
1414*1c12ee1eSDan Willemsen}
1415