xref: /aosp_15_r20/external/golang-protobuf/internal/encoding/text/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 text_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/text"
17*1c12ee1eSDan Willemsen	"google.golang.org/protobuf/internal/flags"
18*1c12ee1eSDan Willemsen)
19*1c12ee1eSDan Willemsen
20*1c12ee1eSDan Willemsenvar eofErr = text.ErrUnexpectedEOF.Error()
21*1c12ee1eSDan Willemsen
22*1c12ee1eSDan Willemsentype R struct {
23*1c12ee1eSDan Willemsen	// K is expected Kind of the returned Token object from calling Decoder.Read.
24*1c12ee1eSDan Willemsen	K text.Kind
25*1c12ee1eSDan Willemsen	// E is expected error substring from calling Decoder.Read if set.
26*1c12ee1eSDan Willemsen	E string
27*1c12ee1eSDan Willemsen	// T contains NT (if K is Name) or ST (if K is Scalar) or nil (others)
28*1c12ee1eSDan Willemsen	T interface{}
29*1c12ee1eSDan Willemsen	// P is expected Token.Pos if set > 0.
30*1c12ee1eSDan Willemsen	P int
31*1c12ee1eSDan Willemsen	// RS is expected result from Token.RawString() if not empty.
32*1c12ee1eSDan Willemsen	RS string
33*1c12ee1eSDan Willemsen}
34*1c12ee1eSDan Willemsen
35*1c12ee1eSDan Willemsen// NT contains data for checking against a name token.
36*1c12ee1eSDan Willemsentype NT struct {
37*1c12ee1eSDan Willemsen	K text.NameKind
38*1c12ee1eSDan Willemsen	// Sep is true if name token should have separator character, else false.
39*1c12ee1eSDan Willemsen	Sep bool
40*1c12ee1eSDan Willemsen	// If K is IdentName or TypeName, invoke corresponding getter and compare against this field.
41*1c12ee1eSDan Willemsen	S string
42*1c12ee1eSDan Willemsen	// If K is FieldNumber, invoke getter and compare against this field.
43*1c12ee1eSDan Willemsen	N int32
44*1c12ee1eSDan Willemsen}
45*1c12ee1eSDan Willemsen
46*1c12ee1eSDan Willemsen// ST contains data for checking against a scalar token.
47*1c12ee1eSDan Willemsentype ST struct {
48*1c12ee1eSDan Willemsen	// checker that is expected to return OK.
49*1c12ee1eSDan Willemsen	ok checker
50*1c12ee1eSDan Willemsen	// checker that is expected to return not OK.
51*1c12ee1eSDan Willemsen	nok checker
52*1c12ee1eSDan Willemsen}
53*1c12ee1eSDan Willemsen
54*1c12ee1eSDan Willemsen// checker provides API for the token wrapper API call types Str, Enum, Bool,
55*1c12ee1eSDan Willemsen// Uint64, Uint32, Int64, Int32, Float64, Float32.
56*1c12ee1eSDan Willemsentype checker interface {
57*1c12ee1eSDan Willemsen	// checkOk checks and expects for token API call to return ok and compare
58*1c12ee1eSDan Willemsen	// against implementation-stored value. Returns empty string if success,
59*1c12ee1eSDan Willemsen	// else returns error message describing the error.
60*1c12ee1eSDan Willemsen	checkOk(text.Token) string
61*1c12ee1eSDan Willemsen	// checkNok checks and expects for token API call to return not ok. Returns
62*1c12ee1eSDan Willemsen	// empty string if success, else returns error message describing the error.
63*1c12ee1eSDan Willemsen	checkNok(text.Token) string
64*1c12ee1eSDan Willemsen}
65*1c12ee1eSDan Willemsen
66*1c12ee1eSDan Willemsentype Str struct {
67*1c12ee1eSDan Willemsen	val string
68*1c12ee1eSDan Willemsen}
69*1c12ee1eSDan Willemsen
70*1c12ee1eSDan Willemsenfunc (s Str) checkOk(tok text.Token) string {
71*1c12ee1eSDan Willemsen	got, ok := tok.String()
72*1c12ee1eSDan Willemsen	if !ok {
73*1c12ee1eSDan Willemsen		return fmt.Sprintf("Token.String() returned not OK for token: %v", tok.RawString())
74*1c12ee1eSDan Willemsen	}
75*1c12ee1eSDan Willemsen	if got != s.val {
76*1c12ee1eSDan Willemsen		return fmt.Sprintf("Token.String() got %q want %q for token: %v", got, s.val, tok.RawString())
77*1c12ee1eSDan Willemsen	}
78*1c12ee1eSDan Willemsen	return ""
79*1c12ee1eSDan Willemsen}
80*1c12ee1eSDan Willemsen
81*1c12ee1eSDan Willemsenfunc (s Str) checkNok(tok text.Token) string {
82*1c12ee1eSDan Willemsen	if _, ok := tok.String(); ok {
83*1c12ee1eSDan Willemsen		return fmt.Sprintf("Token.String() returned OK for token: %v", tok.RawString())
84*1c12ee1eSDan Willemsen	}
85*1c12ee1eSDan Willemsen	return ""
86*1c12ee1eSDan Willemsen}
87*1c12ee1eSDan Willemsen
88*1c12ee1eSDan Willemsentype Enum struct {
89*1c12ee1eSDan Willemsen	val string
90*1c12ee1eSDan Willemsen}
91*1c12ee1eSDan Willemsen
92*1c12ee1eSDan Willemsenfunc (e Enum) checkOk(tok text.Token) string {
93*1c12ee1eSDan Willemsen	got, ok := tok.Enum()
94*1c12ee1eSDan Willemsen	if !ok {
95*1c12ee1eSDan Willemsen		return fmt.Sprintf("Token.Enum() returned not OK for token: %v", tok.RawString())
96*1c12ee1eSDan Willemsen	}
97*1c12ee1eSDan Willemsen	if got != e.val {
98*1c12ee1eSDan Willemsen		return fmt.Sprintf("Token.Enum() got %q want %q for token: %v", got, e.val, tok.RawString())
99*1c12ee1eSDan Willemsen	}
100*1c12ee1eSDan Willemsen	return ""
101*1c12ee1eSDan Willemsen}
102*1c12ee1eSDan Willemsen
103*1c12ee1eSDan Willemsenfunc (e Enum) checkNok(tok text.Token) string {
104*1c12ee1eSDan Willemsen	if _, ok := tok.Enum(); ok {
105*1c12ee1eSDan Willemsen		return fmt.Sprintf("Token.Enum() returned OK for token: %v", tok.RawString())
106*1c12ee1eSDan Willemsen	}
107*1c12ee1eSDan Willemsen	return ""
108*1c12ee1eSDan Willemsen}
109*1c12ee1eSDan Willemsen
110*1c12ee1eSDan Willemsentype Bool struct {
111*1c12ee1eSDan Willemsen	val bool
112*1c12ee1eSDan Willemsen}
113*1c12ee1eSDan Willemsen
114*1c12ee1eSDan Willemsenfunc (b Bool) checkOk(tok text.Token) string {
115*1c12ee1eSDan Willemsen	got, ok := tok.Bool()
116*1c12ee1eSDan Willemsen	if !ok {
117*1c12ee1eSDan Willemsen		return fmt.Sprintf("Token.Bool() returned not OK for token: %v", tok.RawString())
118*1c12ee1eSDan Willemsen	}
119*1c12ee1eSDan Willemsen	if got != b.val {
120*1c12ee1eSDan Willemsen		return fmt.Sprintf("Token.Bool() got %v want %v for token: %v", got, b.val, tok.RawString())
121*1c12ee1eSDan Willemsen	}
122*1c12ee1eSDan Willemsen	return ""
123*1c12ee1eSDan Willemsen}
124*1c12ee1eSDan Willemsen
125*1c12ee1eSDan Willemsenfunc (b Bool) checkNok(tok text.Token) string {
126*1c12ee1eSDan Willemsen	if _, ok := tok.Bool(); ok {
127*1c12ee1eSDan Willemsen		return fmt.Sprintf("Token.Bool() returned OK for token: %v", tok.RawString())
128*1c12ee1eSDan Willemsen	}
129*1c12ee1eSDan Willemsen	return ""
130*1c12ee1eSDan Willemsen}
131*1c12ee1eSDan Willemsen
132*1c12ee1eSDan Willemsentype Uint64 struct {
133*1c12ee1eSDan Willemsen	val uint64
134*1c12ee1eSDan Willemsen}
135*1c12ee1eSDan Willemsen
136*1c12ee1eSDan Willemsenfunc (n Uint64) checkOk(tok text.Token) string {
137*1c12ee1eSDan Willemsen	got, ok := tok.Uint64()
138*1c12ee1eSDan Willemsen	if !ok {
139*1c12ee1eSDan Willemsen		return fmt.Sprintf("Token.Uint64() returned not OK for token: %v", tok.RawString())
140*1c12ee1eSDan Willemsen	}
141*1c12ee1eSDan Willemsen	if got != n.val {
142*1c12ee1eSDan Willemsen		return fmt.Sprintf("Token.Uint64() got %v want %v for token: %v", got, n.val, tok.RawString())
143*1c12ee1eSDan Willemsen	}
144*1c12ee1eSDan Willemsen	return ""
145*1c12ee1eSDan Willemsen}
146*1c12ee1eSDan Willemsen
147*1c12ee1eSDan Willemsenfunc (n Uint64) checkNok(tok text.Token) string {
148*1c12ee1eSDan Willemsen	if _, ok := tok.Uint64(); ok {
149*1c12ee1eSDan Willemsen		return fmt.Sprintf("Token.Uint64() returned OK for token: %v", tok.RawString())
150*1c12ee1eSDan Willemsen	}
151*1c12ee1eSDan Willemsen	return ""
152*1c12ee1eSDan Willemsen}
153*1c12ee1eSDan Willemsen
154*1c12ee1eSDan Willemsentype Uint32 struct {
155*1c12ee1eSDan Willemsen	val uint32
156*1c12ee1eSDan Willemsen}
157*1c12ee1eSDan Willemsen
158*1c12ee1eSDan Willemsenfunc (n Uint32) checkOk(tok text.Token) string {
159*1c12ee1eSDan Willemsen	got, ok := tok.Uint32()
160*1c12ee1eSDan Willemsen	if !ok {
161*1c12ee1eSDan Willemsen		return fmt.Sprintf("Token.Uint32() returned not OK for token: %v", tok.RawString())
162*1c12ee1eSDan Willemsen	}
163*1c12ee1eSDan Willemsen	if got != n.val {
164*1c12ee1eSDan Willemsen		return fmt.Sprintf("Token.Uint32() got %v want %v for token: %v", got, n.val, tok.RawString())
165*1c12ee1eSDan Willemsen	}
166*1c12ee1eSDan Willemsen	return ""
167*1c12ee1eSDan Willemsen}
168*1c12ee1eSDan Willemsen
169*1c12ee1eSDan Willemsenfunc (n Uint32) checkNok(tok text.Token) string {
170*1c12ee1eSDan Willemsen	if _, ok := tok.Uint32(); ok {
171*1c12ee1eSDan Willemsen		return fmt.Sprintf("Token.Uint32() returned OK for token: %v", tok.RawString())
172*1c12ee1eSDan Willemsen	}
173*1c12ee1eSDan Willemsen	return ""
174*1c12ee1eSDan Willemsen}
175*1c12ee1eSDan Willemsen
176*1c12ee1eSDan Willemsentype Int64 struct {
177*1c12ee1eSDan Willemsen	val int64
178*1c12ee1eSDan Willemsen}
179*1c12ee1eSDan Willemsen
180*1c12ee1eSDan Willemsenfunc (n Int64) checkOk(tok text.Token) string {
181*1c12ee1eSDan Willemsen	got, ok := tok.Int64()
182*1c12ee1eSDan Willemsen	if !ok {
183*1c12ee1eSDan Willemsen		return fmt.Sprintf("Token.Int64() returned not OK for token: %v", tok.RawString())
184*1c12ee1eSDan Willemsen	}
185*1c12ee1eSDan Willemsen	if got != n.val {
186*1c12ee1eSDan Willemsen		return fmt.Sprintf("Token.Int64() got %v want %v for token: %v", got, n.val, tok.RawString())
187*1c12ee1eSDan Willemsen	}
188*1c12ee1eSDan Willemsen	return ""
189*1c12ee1eSDan Willemsen}
190*1c12ee1eSDan Willemsen
191*1c12ee1eSDan Willemsenfunc (n Int64) checkNok(tok text.Token) string {
192*1c12ee1eSDan Willemsen	if _, ok := tok.Int64(); ok {
193*1c12ee1eSDan Willemsen		return fmt.Sprintf("Token.Int64() returned OK for token: %v", tok.RawString())
194*1c12ee1eSDan Willemsen	}
195*1c12ee1eSDan Willemsen	return ""
196*1c12ee1eSDan Willemsen}
197*1c12ee1eSDan Willemsen
198*1c12ee1eSDan Willemsentype Int32 struct {
199*1c12ee1eSDan Willemsen	val int32
200*1c12ee1eSDan Willemsen}
201*1c12ee1eSDan Willemsen
202*1c12ee1eSDan Willemsenfunc (n Int32) checkOk(tok text.Token) string {
203*1c12ee1eSDan Willemsen	got, ok := tok.Int32()
204*1c12ee1eSDan Willemsen	if !ok {
205*1c12ee1eSDan Willemsen		return fmt.Sprintf("Token.Int32() returned not OK for token: %v", tok.RawString())
206*1c12ee1eSDan Willemsen	}
207*1c12ee1eSDan Willemsen	if got != n.val {
208*1c12ee1eSDan Willemsen		return fmt.Sprintf("Token.Int32() got %v want %v for token: %v", got, n.val, tok.RawString())
209*1c12ee1eSDan Willemsen	}
210*1c12ee1eSDan Willemsen	return ""
211*1c12ee1eSDan Willemsen}
212*1c12ee1eSDan Willemsen
213*1c12ee1eSDan Willemsenfunc (n Int32) checkNok(tok text.Token) string {
214*1c12ee1eSDan Willemsen	if _, ok := tok.Int32(); ok {
215*1c12ee1eSDan Willemsen		return fmt.Sprintf("Token.Int32() returned OK for token: %v", tok.RawString())
216*1c12ee1eSDan Willemsen	}
217*1c12ee1eSDan Willemsen	return ""
218*1c12ee1eSDan Willemsen}
219*1c12ee1eSDan Willemsen
220*1c12ee1eSDan Willemsentype Float64 struct {
221*1c12ee1eSDan Willemsen	val float64
222*1c12ee1eSDan Willemsen}
223*1c12ee1eSDan Willemsen
224*1c12ee1eSDan Willemsenfunc (n Float64) checkOk(tok text.Token) string {
225*1c12ee1eSDan Willemsen	got, ok := tok.Float64()
226*1c12ee1eSDan Willemsen	if !ok {
227*1c12ee1eSDan Willemsen		return fmt.Sprintf("Token.Float64() returned not OK for token: %v", tok.RawString())
228*1c12ee1eSDan Willemsen	}
229*1c12ee1eSDan Willemsen	if math.Float64bits(got) != math.Float64bits(n.val) {
230*1c12ee1eSDan Willemsen		return fmt.Sprintf("Token.Float64() got %v want %v for token: %v", got, n.val, tok.RawString())
231*1c12ee1eSDan Willemsen	}
232*1c12ee1eSDan Willemsen	return ""
233*1c12ee1eSDan Willemsen}
234*1c12ee1eSDan Willemsen
235*1c12ee1eSDan Willemsenfunc (n Float64) checkNok(tok text.Token) string {
236*1c12ee1eSDan Willemsen	if _, ok := tok.Float64(); ok {
237*1c12ee1eSDan Willemsen		return fmt.Sprintf("Token.Float64() returned OK for token: %v", tok.RawString())
238*1c12ee1eSDan Willemsen	}
239*1c12ee1eSDan Willemsen	return ""
240*1c12ee1eSDan Willemsen}
241*1c12ee1eSDan Willemsen
242*1c12ee1eSDan Willemsentype Float32 struct {
243*1c12ee1eSDan Willemsen	val float32
244*1c12ee1eSDan Willemsen}
245*1c12ee1eSDan Willemsen
246*1c12ee1eSDan Willemsenfunc (n Float32) checkOk(tok text.Token) string {
247*1c12ee1eSDan Willemsen	got, ok := tok.Float32()
248*1c12ee1eSDan Willemsen	if !ok {
249*1c12ee1eSDan Willemsen		return fmt.Sprintf("Token.Float32() returned not OK for token: %v", tok.RawString())
250*1c12ee1eSDan Willemsen	}
251*1c12ee1eSDan Willemsen	if math.Float32bits(got) != math.Float32bits(n.val) {
252*1c12ee1eSDan Willemsen		return fmt.Sprintf("Token.Float32() got %v want %v for token: %v", got, n.val, tok.RawString())
253*1c12ee1eSDan Willemsen	}
254*1c12ee1eSDan Willemsen	return ""
255*1c12ee1eSDan Willemsen}
256*1c12ee1eSDan Willemsen
257*1c12ee1eSDan Willemsenfunc (n Float32) checkNok(tok text.Token) string {
258*1c12ee1eSDan Willemsen	if _, ok := tok.Float32(); ok {
259*1c12ee1eSDan Willemsen		return fmt.Sprintf("Token.Float32() returned OK for token: %v", tok.RawString())
260*1c12ee1eSDan Willemsen	}
261*1c12ee1eSDan Willemsen	return ""
262*1c12ee1eSDan Willemsen}
263*1c12ee1eSDan Willemsen
264*1c12ee1eSDan Willemsenfunc TestDecoder(t *testing.T) {
265*1c12ee1eSDan Willemsen	const space = " \n\r\t"
266*1c12ee1eSDan Willemsen	tests := []struct {
267*1c12ee1eSDan Willemsen		in string
268*1c12ee1eSDan Willemsen		// want is a list of expected Tokens returned from calling Decoder.Read.
269*1c12ee1eSDan Willemsen		// An item makes the test code invoke Decoder.Read and compare against
270*1c12ee1eSDan Willemsen		// R.K and R.E. If R.K is Name, it compares
271*1c12ee1eSDan Willemsen		want []R
272*1c12ee1eSDan Willemsen	}{
273*1c12ee1eSDan Willemsen		{
274*1c12ee1eSDan Willemsen			in:   "",
275*1c12ee1eSDan Willemsen			want: []R{{K: text.EOF}},
276*1c12ee1eSDan Willemsen		},
277*1c12ee1eSDan Willemsen		{
278*1c12ee1eSDan Willemsen			in:   "# comment",
279*1c12ee1eSDan Willemsen			want: []R{{K: text.EOF}},
280*1c12ee1eSDan Willemsen		},
281*1c12ee1eSDan Willemsen		{
282*1c12ee1eSDan Willemsen			in:   space + "# comment" + space,
283*1c12ee1eSDan Willemsen			want: []R{{K: text.EOF}},
284*1c12ee1eSDan Willemsen		},
285*1c12ee1eSDan Willemsen		{
286*1c12ee1eSDan Willemsen			in:   space,
287*1c12ee1eSDan Willemsen			want: []R{{K: text.EOF, P: len(space)}},
288*1c12ee1eSDan Willemsen		},
289*1c12ee1eSDan Willemsen		{
290*1c12ee1eSDan Willemsen			// Calling Read after EOF will keep returning EOF for
291*1c12ee1eSDan Willemsen			// succeeding Read calls.
292*1c12ee1eSDan Willemsen			in: space,
293*1c12ee1eSDan Willemsen			want: []R{
294*1c12ee1eSDan Willemsen				{K: text.EOF},
295*1c12ee1eSDan Willemsen				{K: text.EOF},
296*1c12ee1eSDan Willemsen				{K: text.EOF},
297*1c12ee1eSDan Willemsen			},
298*1c12ee1eSDan Willemsen		},
299*1c12ee1eSDan Willemsen		{
300*1c12ee1eSDan Willemsen			// NUL is an invalid whitespace since C++ uses C-strings.
301*1c12ee1eSDan Willemsen			in:   "\x00",
302*1c12ee1eSDan Willemsen			want: []R{{E: "invalid field name: \x00"}},
303*1c12ee1eSDan Willemsen		},
304*1c12ee1eSDan Willemsen
305*1c12ee1eSDan Willemsen		// Field names.
306*1c12ee1eSDan Willemsen		{
307*1c12ee1eSDan Willemsen			in: "name",
308*1c12ee1eSDan Willemsen			want: []R{
309*1c12ee1eSDan Willemsen				{K: text.Name, T: NT{K: text.IdentName, S: "name"}, RS: "name"},
310*1c12ee1eSDan Willemsen				{E: eofErr},
311*1c12ee1eSDan Willemsen			},
312*1c12ee1eSDan Willemsen		},
313*1c12ee1eSDan Willemsen		{
314*1c12ee1eSDan Willemsen			in: space + "name:" + space,
315*1c12ee1eSDan Willemsen			want: []R{
316*1c12ee1eSDan Willemsen				{K: text.Name, T: NT{K: text.IdentName, Sep: true, S: "name"}},
317*1c12ee1eSDan Willemsen				{E: eofErr},
318*1c12ee1eSDan Willemsen			},
319*1c12ee1eSDan Willemsen		},
320*1c12ee1eSDan Willemsen		{
321*1c12ee1eSDan Willemsen			in: space + "name" + space + ":" + space,
322*1c12ee1eSDan Willemsen			want: []R{
323*1c12ee1eSDan Willemsen				{K: text.Name, T: NT{K: text.IdentName, Sep: true, S: "name"}},
324*1c12ee1eSDan Willemsen				{E: eofErr},
325*1c12ee1eSDan Willemsen			},
326*1c12ee1eSDan Willemsen		},
327*1c12ee1eSDan Willemsen		{
328*1c12ee1eSDan Willemsen			in: "name # comment",
329*1c12ee1eSDan Willemsen			want: []R{
330*1c12ee1eSDan Willemsen				{K: text.Name, T: NT{K: text.IdentName, S: "name"}},
331*1c12ee1eSDan Willemsen				{E: eofErr},
332*1c12ee1eSDan Willemsen			},
333*1c12ee1eSDan Willemsen		},
334*1c12ee1eSDan Willemsen		{
335*1c12ee1eSDan Willemsen			// Comments only extend until the newline.
336*1c12ee1eSDan Willemsen			in: "# comment \nname",
337*1c12ee1eSDan Willemsen			want: []R{
338*1c12ee1eSDan Willemsen				{K: text.Name, T: NT{K: text.IdentName, S: "name"}, P: 11},
339*1c12ee1eSDan Willemsen			},
340*1c12ee1eSDan Willemsen		},
341*1c12ee1eSDan Willemsen		{
342*1c12ee1eSDan Willemsen			in: "name # comment \n:",
343*1c12ee1eSDan Willemsen			want: []R{
344*1c12ee1eSDan Willemsen				{K: text.Name, T: NT{K: text.IdentName, Sep: true, S: "name"}},
345*1c12ee1eSDan Willemsen			},
346*1c12ee1eSDan Willemsen		},
347*1c12ee1eSDan Willemsen		{
348*1c12ee1eSDan Willemsen			in: "name123",
349*1c12ee1eSDan Willemsen			want: []R{
350*1c12ee1eSDan Willemsen				{K: text.Name, T: NT{K: text.IdentName, S: "name123"}},
351*1c12ee1eSDan Willemsen			},
352*1c12ee1eSDan Willemsen		},
353*1c12ee1eSDan Willemsen		{
354*1c12ee1eSDan Willemsen			in: "name_123",
355*1c12ee1eSDan Willemsen			want: []R{
356*1c12ee1eSDan Willemsen				{K: text.Name, T: NT{K: text.IdentName, S: "name_123"}},
357*1c12ee1eSDan Willemsen			},
358*1c12ee1eSDan Willemsen		},
359*1c12ee1eSDan Willemsen		{
360*1c12ee1eSDan Willemsen			in: "_123",
361*1c12ee1eSDan Willemsen			want: []R{
362*1c12ee1eSDan Willemsen				{K: text.Name, T: NT{K: text.IdentName, S: "_123"}},
363*1c12ee1eSDan Willemsen			},
364*1c12ee1eSDan Willemsen		},
365*1c12ee1eSDan Willemsen		{
366*1c12ee1eSDan Willemsen			in:   ":",
367*1c12ee1eSDan Willemsen			want: []R{{E: "syntax error (line 1:1): invalid field name: :"}},
368*1c12ee1eSDan Willemsen		},
369*1c12ee1eSDan Willemsen		{
370*1c12ee1eSDan Willemsen			in:   "\n\n\n {",
371*1c12ee1eSDan Willemsen			want: []R{{E: "syntax error (line 4:2): invalid field name: {"}},
372*1c12ee1eSDan Willemsen		},
373*1c12ee1eSDan Willemsen		{
374*1c12ee1eSDan Willemsen			in:   "123name",
375*1c12ee1eSDan Willemsen			want: []R{{E: "invalid field name: 123name"}},
376*1c12ee1eSDan Willemsen		},
377*1c12ee1eSDan Willemsen		{
378*1c12ee1eSDan Willemsen			in:   `/`,
379*1c12ee1eSDan Willemsen			want: []R{{E: `invalid field name: /`}},
380*1c12ee1eSDan Willemsen		},
381*1c12ee1eSDan Willemsen		{
382*1c12ee1eSDan Willemsen			in:   `世界`,
383*1c12ee1eSDan Willemsen			want: []R{{E: `invalid field name: 世`}},
384*1c12ee1eSDan Willemsen		},
385*1c12ee1eSDan Willemsen		{
386*1c12ee1eSDan Willemsen			in:   `1a/b`,
387*1c12ee1eSDan Willemsen			want: []R{{E: `invalid field name: 1a`}},
388*1c12ee1eSDan Willemsen		},
389*1c12ee1eSDan Willemsen		{
390*1c12ee1eSDan Willemsen			in:   `1c\d`,
391*1c12ee1eSDan Willemsen			want: []R{{E: `invalid field name: 1c`}},
392*1c12ee1eSDan Willemsen		},
393*1c12ee1eSDan Willemsen		{
394*1c12ee1eSDan Willemsen			in:   "\x84f",
395*1c12ee1eSDan Willemsen			want: []R{{E: "invalid field name: \x84"}},
396*1c12ee1eSDan Willemsen		},
397*1c12ee1eSDan Willemsen		{
398*1c12ee1eSDan Willemsen			in:   "\uFFFDxxx",
399*1c12ee1eSDan Willemsen			want: []R{{E: "invalid field name: \uFFFD"}},
400*1c12ee1eSDan Willemsen		},
401*1c12ee1eSDan Willemsen		{
402*1c12ee1eSDan Willemsen			in:   "-a234567890123456789012345678901234567890abc",
403*1c12ee1eSDan Willemsen			want: []R{{E: "invalid field name: -a2345678901234567890123456789012…"}},
404*1c12ee1eSDan Willemsen		},
405*1c12ee1eSDan Willemsen		{
406*1c12ee1eSDan Willemsen			in: "[type]",
407*1c12ee1eSDan Willemsen			want: []R{
408*1c12ee1eSDan Willemsen				{K: text.Name, T: NT{K: text.TypeName, S: "type"}, RS: "[type]"},
409*1c12ee1eSDan Willemsen			},
410*1c12ee1eSDan Willemsen		},
411*1c12ee1eSDan Willemsen		{
412*1c12ee1eSDan Willemsen			// V1 allows this syntax. C++ does not, however, C++ also fails if
413*1c12ee1eSDan Willemsen			// field is Any and does not contain '/'.
414*1c12ee1eSDan Willemsen			in: "[/type]",
415*1c12ee1eSDan Willemsen			want: []R{
416*1c12ee1eSDan Willemsen				{K: text.Name, T: NT{K: text.TypeName, S: "/type"}},
417*1c12ee1eSDan Willemsen			},
418*1c12ee1eSDan Willemsen		},
419*1c12ee1eSDan Willemsen		{
420*1c12ee1eSDan Willemsen			in:   "[.type]",
421*1c12ee1eSDan Willemsen			want: []R{{E: "invalid type URL/extension field name: [.type]"}},
422*1c12ee1eSDan Willemsen		},
423*1c12ee1eSDan Willemsen		{
424*1c12ee1eSDan Willemsen			in: "[pkg.Foo.extension_field]",
425*1c12ee1eSDan Willemsen			want: []R{
426*1c12ee1eSDan Willemsen				{K: text.Name, T: NT{K: text.TypeName, S: "pkg.Foo.extension_field"}},
427*1c12ee1eSDan Willemsen			},
428*1c12ee1eSDan Willemsen		},
429*1c12ee1eSDan Willemsen		{
430*1c12ee1eSDan Willemsen			in: "[domain.com/type]",
431*1c12ee1eSDan Willemsen			want: []R{
432*1c12ee1eSDan Willemsen				{K: text.Name, T: NT{K: text.TypeName, S: "domain.com/type"}},
433*1c12ee1eSDan Willemsen			},
434*1c12ee1eSDan Willemsen		},
435*1c12ee1eSDan Willemsen		{
436*1c12ee1eSDan Willemsen			in: "[domain.com/pkg.type]",
437*1c12ee1eSDan Willemsen			want: []R{
438*1c12ee1eSDan Willemsen				{K: text.Name, T: NT{K: text.TypeName, S: "domain.com/pkg.type"}},
439*1c12ee1eSDan Willemsen			},
440*1c12ee1eSDan Willemsen		},
441*1c12ee1eSDan Willemsen		{
442*1c12ee1eSDan Willemsen			in: "[sub.domain.com\x2fpath\x2fto\x2fproto.package.name]",
443*1c12ee1eSDan Willemsen			want: []R{
444*1c12ee1eSDan Willemsen				{
445*1c12ee1eSDan Willemsen					K: text.Name,
446*1c12ee1eSDan Willemsen					T: NT{
447*1c12ee1eSDan Willemsen						K: text.TypeName,
448*1c12ee1eSDan Willemsen						S: "sub.domain.com/path/to/proto.package.name",
449*1c12ee1eSDan Willemsen					},
450*1c12ee1eSDan Willemsen					RS: "[sub.domain.com\x2fpath\x2fto\x2fproto.package.name]",
451*1c12ee1eSDan Willemsen				},
452*1c12ee1eSDan Willemsen			},
453*1c12ee1eSDan Willemsen		},
454*1c12ee1eSDan Willemsen		{
455*1c12ee1eSDan Willemsen			// V2 no longer allows a quoted string for the Any type URL.
456*1c12ee1eSDan Willemsen			in:   `["domain.com/pkg.type"]`,
457*1c12ee1eSDan Willemsen			want: []R{{E: `invalid type URL/extension field name: ["`}},
458*1c12ee1eSDan Willemsen		},
459*1c12ee1eSDan Willemsen		{
460*1c12ee1eSDan Willemsen			// V2 no longer allows a quoted string for the Any type URL.
461*1c12ee1eSDan Willemsen			in:   `['domain.com/pkg.type']`,
462*1c12ee1eSDan Willemsen			want: []R{{E: `invalid type URL/extension field name: ['`}},
463*1c12ee1eSDan Willemsen		},
464*1c12ee1eSDan Willemsen		{
465*1c12ee1eSDan Willemsen			in:   "[pkg.Foo.extension_field:",
466*1c12ee1eSDan Willemsen			want: []R{{E: "invalid type URL/extension field name: [pkg.Foo.extension_field:"}},
467*1c12ee1eSDan Willemsen		},
468*1c12ee1eSDan Willemsen		{
469*1c12ee1eSDan Willemsen			// V2 no longer allows whitespace within identifier "word".
470*1c12ee1eSDan Willemsen			in:   "[proto.packa ge.field]",
471*1c12ee1eSDan Willemsen			want: []R{{E: "invalid type URL/extension field name: [proto.packa g"}},
472*1c12ee1eSDan Willemsen		},
473*1c12ee1eSDan Willemsen		{
474*1c12ee1eSDan Willemsen			// V2 no longer allows comments within identifier "word".
475*1c12ee1eSDan Willemsen			in:   "[proto.packa # comment\n ge.field]",
476*1c12ee1eSDan Willemsen			want: []R{{E: "invalid type URL/extension field name: [proto.packa # comment\n g"}},
477*1c12ee1eSDan Willemsen		},
478*1c12ee1eSDan Willemsen		{
479*1c12ee1eSDan Willemsen			in:   "[proto.package.]",
480*1c12ee1eSDan Willemsen			want: []R{{E: "invalid type URL/extension field name: [proto.package."}},
481*1c12ee1eSDan Willemsen		},
482*1c12ee1eSDan Willemsen		{
483*1c12ee1eSDan Willemsen			in:   "[proto.package/]",
484*1c12ee1eSDan Willemsen			want: []R{{E: "invalid type URL/extension field name: [proto.package/"}},
485*1c12ee1eSDan Willemsen		},
486*1c12ee1eSDan Willemsen		{
487*1c12ee1eSDan Willemsen			in: `message_field{[bad@]`,
488*1c12ee1eSDan Willemsen			want: []R{
489*1c12ee1eSDan Willemsen				{K: text.Name},
490*1c12ee1eSDan Willemsen				{K: text.MessageOpen},
491*1c12ee1eSDan Willemsen				{E: `invalid type URL/extension field name: [bad@`},
492*1c12ee1eSDan Willemsen			},
493*1c12ee1eSDan Willemsen		},
494*1c12ee1eSDan Willemsen		{
495*1c12ee1eSDan Willemsen			in: `message_field{[invalid//type]`,
496*1c12ee1eSDan Willemsen			want: []R{
497*1c12ee1eSDan Willemsen				{K: text.Name},
498*1c12ee1eSDan Willemsen				{K: text.MessageOpen},
499*1c12ee1eSDan Willemsen				{E: `invalid type URL/extension field name: [invalid//`},
500*1c12ee1eSDan Willemsen			},
501*1c12ee1eSDan Willemsen		},
502*1c12ee1eSDan Willemsen		{
503*1c12ee1eSDan Willemsen			in: `message_field{[proto.package.]`,
504*1c12ee1eSDan Willemsen			want: []R{
505*1c12ee1eSDan Willemsen				{K: text.Name},
506*1c12ee1eSDan Willemsen				{K: text.MessageOpen},
507*1c12ee1eSDan Willemsen				{E: `invalid type URL/extension field name: [proto.package.`},
508*1c12ee1eSDan Willemsen			},
509*1c12ee1eSDan Willemsen		},
510*1c12ee1eSDan Willemsen		{
511*1c12ee1eSDan Willemsen			in:   "[proto.package",
512*1c12ee1eSDan Willemsen			want: []R{{E: eofErr}},
513*1c12ee1eSDan Willemsen		},
514*1c12ee1eSDan Willemsen		{
515*1c12ee1eSDan Willemsen			in: "[" + space + "type" + space + "]" + space + ":",
516*1c12ee1eSDan Willemsen			want: []R{
517*1c12ee1eSDan Willemsen				{
518*1c12ee1eSDan Willemsen					K: text.Name,
519*1c12ee1eSDan Willemsen					T: NT{
520*1c12ee1eSDan Willemsen						K:   text.TypeName,
521*1c12ee1eSDan Willemsen						Sep: true,
522*1c12ee1eSDan Willemsen						S:   "type",
523*1c12ee1eSDan Willemsen					},
524*1c12ee1eSDan Willemsen					RS: "[" + space + "type" + space + "]",
525*1c12ee1eSDan Willemsen				},
526*1c12ee1eSDan Willemsen			},
527*1c12ee1eSDan Willemsen		},
528*1c12ee1eSDan Willemsen		{
529*1c12ee1eSDan Willemsen			// Whitespaces/comments are only allowed betweeb
530*1c12ee1eSDan Willemsen			in: "[" + space + "domain" + space + "." + space + "com # comment\n" +
531*1c12ee1eSDan Willemsen				"/" + "pkg" + space + "." + space + "type" + space + "]",
532*1c12ee1eSDan Willemsen			want: []R{
533*1c12ee1eSDan Willemsen				{K: text.Name, T: NT{K: text.TypeName, S: "domain.com/pkg.type"}},
534*1c12ee1eSDan Willemsen			},
535*1c12ee1eSDan Willemsen		},
536*1c12ee1eSDan Willemsen		{
537*1c12ee1eSDan Willemsen			in: "42",
538*1c12ee1eSDan Willemsen			want: []R{
539*1c12ee1eSDan Willemsen				{K: text.Name, T: NT{K: text.FieldNumber, N: 42}},
540*1c12ee1eSDan Willemsen			},
541*1c12ee1eSDan Willemsen		},
542*1c12ee1eSDan Willemsen		{
543*1c12ee1eSDan Willemsen			in:   "0x42:",
544*1c12ee1eSDan Willemsen			want: []R{{E: "invalid field number: 0x42"}},
545*1c12ee1eSDan Willemsen		},
546*1c12ee1eSDan Willemsen		{
547*1c12ee1eSDan Willemsen			in:   "042:",
548*1c12ee1eSDan Willemsen			want: []R{{E: "invalid field number: 042"}},
549*1c12ee1eSDan Willemsen		},
550*1c12ee1eSDan Willemsen		{
551*1c12ee1eSDan Willemsen			in:   "123.456:",
552*1c12ee1eSDan Willemsen			want: []R{{E: "invalid field number: 123.456"}},
553*1c12ee1eSDan Willemsen		},
554*1c12ee1eSDan Willemsen		{
555*1c12ee1eSDan Willemsen			in:   "-123",
556*1c12ee1eSDan Willemsen			want: []R{{E: "invalid field number: -123"}},
557*1c12ee1eSDan Willemsen		},
558*1c12ee1eSDan Willemsen		{
559*1c12ee1eSDan Willemsen			in:   "- \t 123.321e6",
560*1c12ee1eSDan Willemsen			want: []R{{E: "invalid field number: -123.321e6"}},
561*1c12ee1eSDan Willemsen		},
562*1c12ee1eSDan Willemsen		{
563*1c12ee1eSDan Willemsen			in:   "-",
564*1c12ee1eSDan Willemsen			want: []R{{E: "invalid field name: -"}},
565*1c12ee1eSDan Willemsen		},
566*1c12ee1eSDan Willemsen		{
567*1c12ee1eSDan Willemsen			in:   "- ",
568*1c12ee1eSDan Willemsen			want: []R{{E: "invalid field name: -"}},
569*1c12ee1eSDan Willemsen		},
570*1c12ee1eSDan Willemsen		{
571*1c12ee1eSDan Willemsen			in:   "- # negative\n 123",
572*1c12ee1eSDan Willemsen			want: []R{{E: "invalid field number: -123"}},
573*1c12ee1eSDan Willemsen		},
574*1c12ee1eSDan Willemsen		{
575*1c12ee1eSDan Willemsen			// Field number > math.MaxInt32.
576*1c12ee1eSDan Willemsen			in:   "2147483648:",
577*1c12ee1eSDan Willemsen			want: []R{{E: "invalid field number: 2147483648"}},
578*1c12ee1eSDan Willemsen		},
579*1c12ee1eSDan Willemsen
580*1c12ee1eSDan Willemsen		// String field value. More string parsing specific testing in
581*1c12ee1eSDan Willemsen		// TestUnmarshalString.
582*1c12ee1eSDan Willemsen		{
583*1c12ee1eSDan Willemsen			in: `name: "hello world"`,
584*1c12ee1eSDan Willemsen			want: []R{
585*1c12ee1eSDan Willemsen				{K: text.Name},
586*1c12ee1eSDan Willemsen				{
587*1c12ee1eSDan Willemsen					K:  text.Scalar,
588*1c12ee1eSDan Willemsen					T:  ST{ok: Str{"hello world"}, nok: Enum{}},
589*1c12ee1eSDan Willemsen					RS: `"hello world"`,
590*1c12ee1eSDan Willemsen				},
591*1c12ee1eSDan Willemsen				{K: text.EOF},
592*1c12ee1eSDan Willemsen			},
593*1c12ee1eSDan Willemsen		},
594*1c12ee1eSDan Willemsen		{
595*1c12ee1eSDan Willemsen			in: `name: 'hello'`,
596*1c12ee1eSDan Willemsen			want: []R{
597*1c12ee1eSDan Willemsen				{K: text.Name},
598*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Str{"hello"}}},
599*1c12ee1eSDan Willemsen			},
600*1c12ee1eSDan Willemsen		},
601*1c12ee1eSDan Willemsen		{
602*1c12ee1eSDan Willemsen			in: `name: "hello'`,
603*1c12ee1eSDan Willemsen			want: []R{
604*1c12ee1eSDan Willemsen				{K: text.Name},
605*1c12ee1eSDan Willemsen				{E: eofErr},
606*1c12ee1eSDan Willemsen			},
607*1c12ee1eSDan Willemsen		},
608*1c12ee1eSDan Willemsen		{
609*1c12ee1eSDan Willemsen			in: `name: 'hello`,
610*1c12ee1eSDan Willemsen			want: []R{
611*1c12ee1eSDan Willemsen				{K: text.Name},
612*1c12ee1eSDan Willemsen				{E: eofErr},
613*1c12ee1eSDan Willemsen			},
614*1c12ee1eSDan Willemsen		},
615*1c12ee1eSDan Willemsen		{
616*1c12ee1eSDan Willemsen			// Field name without separator is ok. prototext package will need
617*1c12ee1eSDan Willemsen			// to determine that this is not valid for scalar values.
618*1c12ee1eSDan Willemsen			in: space + `name` + space + `"hello"` + space,
619*1c12ee1eSDan Willemsen			want: []R{
620*1c12ee1eSDan Willemsen				{K: text.Name},
621*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Str{"hello"}}},
622*1c12ee1eSDan Willemsen			},
623*1c12ee1eSDan Willemsen		},
624*1c12ee1eSDan Willemsen		{
625*1c12ee1eSDan Willemsen			in: `name'hello'`,
626*1c12ee1eSDan Willemsen			want: []R{
627*1c12ee1eSDan Willemsen				{K: text.Name},
628*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Str{"hello"}}},
629*1c12ee1eSDan Willemsen			},
630*1c12ee1eSDan Willemsen		},
631*1c12ee1eSDan Willemsen		{
632*1c12ee1eSDan Willemsen			in: `name: ` + space + `"hello"` + space + `,`,
633*1c12ee1eSDan Willemsen			want: []R{
634*1c12ee1eSDan Willemsen				{K: text.Name},
635*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Str{"hello"}}},
636*1c12ee1eSDan Willemsen				{K: text.EOF},
637*1c12ee1eSDan Willemsen			},
638*1c12ee1eSDan Willemsen		},
639*1c12ee1eSDan Willemsen		{
640*1c12ee1eSDan Willemsen			in: `name` + space + `:` + `"hello"` + space + `;` + space,
641*1c12ee1eSDan Willemsen			want: []R{
642*1c12ee1eSDan Willemsen				{K: text.Name},
643*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Str{"hello"}}},
644*1c12ee1eSDan Willemsen				{K: text.EOF},
645*1c12ee1eSDan Willemsen			},
646*1c12ee1eSDan Willemsen		},
647*1c12ee1eSDan Willemsen		{
648*1c12ee1eSDan Willemsen			in: `name:"hello" , ,`,
649*1c12ee1eSDan Willemsen			want: []R{
650*1c12ee1eSDan Willemsen				{K: text.Name},
651*1c12ee1eSDan Willemsen				{K: text.Scalar},
652*1c12ee1eSDan Willemsen				{E: "(line 1:16): invalid field name: ,"},
653*1c12ee1eSDan Willemsen			},
654*1c12ee1eSDan Willemsen		},
655*1c12ee1eSDan Willemsen		{
656*1c12ee1eSDan Willemsen			in: `name:"hello" , ;`,
657*1c12ee1eSDan Willemsen			want: []R{
658*1c12ee1eSDan Willemsen				{K: text.Name},
659*1c12ee1eSDan Willemsen				{K: text.Scalar},
660*1c12ee1eSDan Willemsen				{E: "(line 1:16): invalid field name: ;"},
661*1c12ee1eSDan Willemsen			},
662*1c12ee1eSDan Willemsen		},
663*1c12ee1eSDan Willemsen		{
664*1c12ee1eSDan Willemsen			in: `name:"hello" name:'world'`,
665*1c12ee1eSDan Willemsen			want: []R{
666*1c12ee1eSDan Willemsen				{K: text.Name},
667*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Str{"hello"}}},
668*1c12ee1eSDan Willemsen				{K: text.Name},
669*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Str{"world"}}},
670*1c12ee1eSDan Willemsen				{K: text.EOF},
671*1c12ee1eSDan Willemsen			},
672*1c12ee1eSDan Willemsen		},
673*1c12ee1eSDan Willemsen		{
674*1c12ee1eSDan Willemsen			in: `name:"hello", name:"world"`,
675*1c12ee1eSDan Willemsen			want: []R{
676*1c12ee1eSDan Willemsen				{K: text.Name},
677*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Str{"hello"}}},
678*1c12ee1eSDan Willemsen				{K: text.Name},
679*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Str{"world"}}},
680*1c12ee1eSDan Willemsen				{K: text.EOF},
681*1c12ee1eSDan Willemsen			},
682*1c12ee1eSDan Willemsen		},
683*1c12ee1eSDan Willemsen		{
684*1c12ee1eSDan Willemsen			in: `name:"hello"; name:"world",`,
685*1c12ee1eSDan Willemsen			want: []R{
686*1c12ee1eSDan Willemsen				{K: text.Name},
687*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Str{"hello"}}},
688*1c12ee1eSDan Willemsen				{K: text.Name},
689*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Str{"world"}}},
690*1c12ee1eSDan Willemsen				{K: text.EOF},
691*1c12ee1eSDan Willemsen			},
692*1c12ee1eSDan Willemsen		},
693*1c12ee1eSDan Willemsen		{
694*1c12ee1eSDan Willemsen			in: `foo:"hello"bar:"world"`,
695*1c12ee1eSDan Willemsen			want: []R{
696*1c12ee1eSDan Willemsen				{K: text.Name, T: NT{K: text.IdentName, Sep: true, S: "foo"}},
697*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Str{"hello"}}},
698*1c12ee1eSDan Willemsen				{K: text.Name, T: NT{K: text.IdentName, Sep: true, S: "bar"}},
699*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Str{"world"}}},
700*1c12ee1eSDan Willemsen				{K: text.EOF},
701*1c12ee1eSDan Willemsen			},
702*1c12ee1eSDan Willemsen		},
703*1c12ee1eSDan Willemsen		{
704*1c12ee1eSDan Willemsen			in: `foo:"hello"[bar]:"world"`,
705*1c12ee1eSDan Willemsen			want: []R{
706*1c12ee1eSDan Willemsen				{K: text.Name, T: NT{K: text.IdentName, Sep: true, S: "foo"}},
707*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Str{"hello"}}},
708*1c12ee1eSDan Willemsen				{K: text.Name, T: NT{K: text.TypeName, Sep: true, S: "bar"}},
709*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Str{"world"}}},
710*1c12ee1eSDan Willemsen				{K: text.EOF},
711*1c12ee1eSDan Willemsen			},
712*1c12ee1eSDan Willemsen		},
713*1c12ee1eSDan Willemsen		{
714*1c12ee1eSDan Willemsen			in: `name:"foo"` + space + `"bar"` + space + `'qux'`,
715*1c12ee1eSDan Willemsen			want: []R{
716*1c12ee1eSDan Willemsen				{K: text.Name, T: NT{K: text.IdentName, Sep: true, S: "name"}},
717*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Str{"foobarqux"}}},
718*1c12ee1eSDan Willemsen				{K: text.EOF},
719*1c12ee1eSDan Willemsen			},
720*1c12ee1eSDan Willemsen		},
721*1c12ee1eSDan Willemsen		{
722*1c12ee1eSDan Willemsen			in: `name:"foo"'bar'"qux"`,
723*1c12ee1eSDan Willemsen			want: []R{
724*1c12ee1eSDan Willemsen				{K: text.Name, T: NT{K: text.IdentName, Sep: true, S: "name"}},
725*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Str{"foobarqux"}}},
726*1c12ee1eSDan Willemsen				{K: text.EOF},
727*1c12ee1eSDan Willemsen			},
728*1c12ee1eSDan Willemsen		},
729*1c12ee1eSDan Willemsen		{
730*1c12ee1eSDan Willemsen			in: `name:"foo"` + space + `"bar" # comment` + "\n'qux' # comment",
731*1c12ee1eSDan Willemsen			want: []R{
732*1c12ee1eSDan Willemsen				{K: text.Name, T: NT{K: text.IdentName, Sep: true, S: "name"}},
733*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Str{"foobarqux"}}},
734*1c12ee1eSDan Willemsen				{K: text.EOF},
735*1c12ee1eSDan Willemsen			},
736*1c12ee1eSDan Willemsen		},
737*1c12ee1eSDan Willemsen
738*1c12ee1eSDan Willemsen		// Lists.
739*1c12ee1eSDan Willemsen		{
740*1c12ee1eSDan Willemsen			in: `name: [`,
741*1c12ee1eSDan Willemsen			want: []R{
742*1c12ee1eSDan Willemsen				{K: text.Name},
743*1c12ee1eSDan Willemsen				{K: text.ListOpen},
744*1c12ee1eSDan Willemsen				{E: eofErr},
745*1c12ee1eSDan Willemsen			},
746*1c12ee1eSDan Willemsen		},
747*1c12ee1eSDan Willemsen		{
748*1c12ee1eSDan Willemsen			in: `name: []`,
749*1c12ee1eSDan Willemsen			want: []R{
750*1c12ee1eSDan Willemsen				{K: text.Name},
751*1c12ee1eSDan Willemsen				{K: text.ListOpen},
752*1c12ee1eSDan Willemsen				{K: text.ListClose},
753*1c12ee1eSDan Willemsen				{K: text.EOF},
754*1c12ee1eSDan Willemsen			},
755*1c12ee1eSDan Willemsen		},
756*1c12ee1eSDan Willemsen		{
757*1c12ee1eSDan Willemsen			in: `name []`,
758*1c12ee1eSDan Willemsen			want: []R{
759*1c12ee1eSDan Willemsen				{K: text.Name},
760*1c12ee1eSDan Willemsen				{K: text.ListOpen},
761*1c12ee1eSDan Willemsen				{K: text.ListClose},
762*1c12ee1eSDan Willemsen				{K: text.EOF},
763*1c12ee1eSDan Willemsen			},
764*1c12ee1eSDan Willemsen		},
765*1c12ee1eSDan Willemsen		{
766*1c12ee1eSDan Willemsen			in: `name: [,`,
767*1c12ee1eSDan Willemsen			want: []R{
768*1c12ee1eSDan Willemsen				{K: text.Name},
769*1c12ee1eSDan Willemsen				{K: text.ListOpen},
770*1c12ee1eSDan Willemsen				{E: `(line 1:8): invalid scalar value: ,`},
771*1c12ee1eSDan Willemsen			},
772*1c12ee1eSDan Willemsen		},
773*1c12ee1eSDan Willemsen		{
774*1c12ee1eSDan Willemsen			in: `name: [0`,
775*1c12ee1eSDan Willemsen			want: []R{
776*1c12ee1eSDan Willemsen				{K: text.Name},
777*1c12ee1eSDan Willemsen				{K: text.ListOpen},
778*1c12ee1eSDan Willemsen				{K: text.Scalar},
779*1c12ee1eSDan Willemsen				{E: eofErr},
780*1c12ee1eSDan Willemsen			},
781*1c12ee1eSDan Willemsen		},
782*1c12ee1eSDan Willemsen		{
783*1c12ee1eSDan Willemsen			in: `name: [` + space + `"hello"` + space + `]` + space,
784*1c12ee1eSDan Willemsen			want: []R{
785*1c12ee1eSDan Willemsen				{K: text.Name},
786*1c12ee1eSDan Willemsen				{K: text.ListOpen},
787*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Str{"hello"}}, P: len(space) + 7},
788*1c12ee1eSDan Willemsen				{K: text.ListClose},
789*1c12ee1eSDan Willemsen				{K: text.EOF},
790*1c12ee1eSDan Willemsen			},
791*1c12ee1eSDan Willemsen		},
792*1c12ee1eSDan Willemsen		{
793*1c12ee1eSDan Willemsen			in: `name: ["hello",]`,
794*1c12ee1eSDan Willemsen			want: []R{
795*1c12ee1eSDan Willemsen				{K: text.Name},
796*1c12ee1eSDan Willemsen				{K: text.ListOpen},
797*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Str{"hello"}}},
798*1c12ee1eSDan Willemsen				{E: `invalid scalar value: ]`},
799*1c12ee1eSDan Willemsen			},
800*1c12ee1eSDan Willemsen		},
801*1c12ee1eSDan Willemsen		{
802*1c12ee1eSDan Willemsen			in: `name: ["foo"` + space + `'bar' "qux"]`,
803*1c12ee1eSDan Willemsen			want: []R{
804*1c12ee1eSDan Willemsen				{K: text.Name},
805*1c12ee1eSDan Willemsen				{K: text.ListOpen},
806*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Str{"foobarqux"}}},
807*1c12ee1eSDan Willemsen				{K: text.ListClose},
808*1c12ee1eSDan Willemsen				{K: text.EOF},
809*1c12ee1eSDan Willemsen			},
810*1c12ee1eSDan Willemsen		},
811*1c12ee1eSDan Willemsen		{
812*1c12ee1eSDan Willemsen			in: `name:` + space + `["foo",` + space + "'bar', # comment\n\n" + `"qux"]`,
813*1c12ee1eSDan Willemsen			want: []R{
814*1c12ee1eSDan Willemsen				{K: text.Name},
815*1c12ee1eSDan Willemsen				{K: text.ListOpen},
816*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Str{"foo"}}},
817*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Str{"bar"}}},
818*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Str{"qux"}}},
819*1c12ee1eSDan Willemsen				{K: text.ListClose},
820*1c12ee1eSDan Willemsen				{K: text.EOF},
821*1c12ee1eSDan Willemsen			},
822*1c12ee1eSDan Willemsen		},
823*1c12ee1eSDan Willemsen
824*1c12ee1eSDan Willemsen		{
825*1c12ee1eSDan Willemsen			// List within list is not allowed.
826*1c12ee1eSDan Willemsen			in: `name: [[]]`,
827*1c12ee1eSDan Willemsen			want: []R{
828*1c12ee1eSDan Willemsen				{K: text.Name},
829*1c12ee1eSDan Willemsen				{K: text.ListOpen},
830*1c12ee1eSDan Willemsen				{E: `syntax error (line 1:8): invalid scalar value: [`},
831*1c12ee1eSDan Willemsen			},
832*1c12ee1eSDan Willemsen		},
833*1c12ee1eSDan Willemsen		{
834*1c12ee1eSDan Willemsen			// List items need to be separated by ,.
835*1c12ee1eSDan Willemsen			in: `name: ["foo" true]`,
836*1c12ee1eSDan Willemsen			want: []R{
837*1c12ee1eSDan Willemsen				{K: text.Name},
838*1c12ee1eSDan Willemsen				{K: text.ListOpen},
839*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Str{"foo"}}},
840*1c12ee1eSDan Willemsen				{E: `syntax error (line 1:14): unexpected character 't'`},
841*1c12ee1eSDan Willemsen			},
842*1c12ee1eSDan Willemsen		},
843*1c12ee1eSDan Willemsen		{
844*1c12ee1eSDan Willemsen			in: `name: ["foo"; "bar"]`,
845*1c12ee1eSDan Willemsen			want: []R{
846*1c12ee1eSDan Willemsen				{K: text.Name},
847*1c12ee1eSDan Willemsen				{K: text.ListOpen},
848*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Str{"foo"}}},
849*1c12ee1eSDan Willemsen				{E: `syntax error (line 1:13): unexpected character ';'`},
850*1c12ee1eSDan Willemsen			},
851*1c12ee1eSDan Willemsen		},
852*1c12ee1eSDan Willemsen		{
853*1c12ee1eSDan Willemsen			in: `name: ["foo", true, ENUM, 1.0]`,
854*1c12ee1eSDan Willemsen			want: []R{
855*1c12ee1eSDan Willemsen				{K: text.Name},
856*1c12ee1eSDan Willemsen				{K: text.ListOpen},
857*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Str{"foo"}}},
858*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Enum{"true"}}},
859*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Enum{"ENUM"}}},
860*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Float32{1.0}}},
861*1c12ee1eSDan Willemsen				{K: text.ListClose},
862*1c12ee1eSDan Willemsen			},
863*1c12ee1eSDan Willemsen		},
864*1c12ee1eSDan Willemsen
865*1c12ee1eSDan Willemsen		// Boolean literal values.
866*1c12ee1eSDan Willemsen		{
867*1c12ee1eSDan Willemsen			in: `name: True`,
868*1c12ee1eSDan Willemsen			want: []R{
869*1c12ee1eSDan Willemsen				{K: text.Name},
870*1c12ee1eSDan Willemsen				{
871*1c12ee1eSDan Willemsen					K: text.Scalar,
872*1c12ee1eSDan Willemsen					T: ST{ok: Bool{true}},
873*1c12ee1eSDan Willemsen				},
874*1c12ee1eSDan Willemsen				{K: text.EOF},
875*1c12ee1eSDan Willemsen			},
876*1c12ee1eSDan Willemsen		},
877*1c12ee1eSDan Willemsen		{
878*1c12ee1eSDan Willemsen			in: `name false`,
879*1c12ee1eSDan Willemsen			want: []R{
880*1c12ee1eSDan Willemsen				{K: text.Name},
881*1c12ee1eSDan Willemsen				{
882*1c12ee1eSDan Willemsen					K: text.Scalar,
883*1c12ee1eSDan Willemsen					T: ST{ok: Bool{false}},
884*1c12ee1eSDan Willemsen				},
885*1c12ee1eSDan Willemsen				{K: text.EOF},
886*1c12ee1eSDan Willemsen			},
887*1c12ee1eSDan Willemsen		},
888*1c12ee1eSDan Willemsen		{
889*1c12ee1eSDan Willemsen			in: `name: [t, f, True, False, true, false, 1, 0, 0x01, 0x00, 01, 00]`,
890*1c12ee1eSDan Willemsen			want: []R{
891*1c12ee1eSDan Willemsen				{K: text.Name},
892*1c12ee1eSDan Willemsen				{K: text.ListOpen},
893*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Bool{true}}},
894*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Bool{false}}},
895*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Bool{true}}},
896*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Bool{false}}},
897*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Bool{true}}},
898*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Bool{false}}},
899*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Bool{true}}},
900*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Bool{false}}},
901*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Bool{true}}},
902*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Bool{false}}},
903*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Bool{true}}},
904*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Bool{false}}},
905*1c12ee1eSDan Willemsen				{K: text.ListClose},
906*1c12ee1eSDan Willemsen			},
907*1c12ee1eSDan Willemsen		},
908*1c12ee1eSDan Willemsen		{
909*1c12ee1eSDan Willemsen			// Looks like boolean but not.
910*1c12ee1eSDan Willemsen			in: `name: [tRUe, falSE, -1, -0, -0x01, -0x00, -01, -00, 0.0]`,
911*1c12ee1eSDan Willemsen			want: []R{
912*1c12ee1eSDan Willemsen				{K: text.Name},
913*1c12ee1eSDan Willemsen				{K: text.ListOpen},
914*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{nok: Bool{}}},
915*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{nok: Bool{}}},
916*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{nok: Bool{}}},
917*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{nok: Bool{}}},
918*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{nok: Bool{}}},
919*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{nok: Bool{}}},
920*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{nok: Bool{}}},
921*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{nok: Bool{}}},
922*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{nok: Bool{}}},
923*1c12ee1eSDan Willemsen				{K: text.ListClose},
924*1c12ee1eSDan Willemsen			},
925*1c12ee1eSDan Willemsen		},
926*1c12ee1eSDan Willemsen		{
927*1c12ee1eSDan Willemsen			in: `foo: true[bar] false`,
928*1c12ee1eSDan Willemsen			want: []R{
929*1c12ee1eSDan Willemsen				{K: text.Name},
930*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Bool{true}}},
931*1c12ee1eSDan Willemsen				{K: text.Name},
932*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Bool{false}}},
933*1c12ee1eSDan Willemsen			},
934*1c12ee1eSDan Willemsen		},
935*1c12ee1eSDan Willemsen
936*1c12ee1eSDan Willemsen		// Enum field values.
937*1c12ee1eSDan Willemsen		{
938*1c12ee1eSDan Willemsen			in: space + `name: ENUM`,
939*1c12ee1eSDan Willemsen			want: []R{
940*1c12ee1eSDan Willemsen				{K: text.Name},
941*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Enum{"ENUM"}}},
942*1c12ee1eSDan Willemsen			},
943*1c12ee1eSDan Willemsen		},
944*1c12ee1eSDan Willemsen		{
945*1c12ee1eSDan Willemsen			in: space + `name:[TRUE, FALSE, T, F, t, f]`,
946*1c12ee1eSDan Willemsen			want: []R{
947*1c12ee1eSDan Willemsen				{K: text.Name},
948*1c12ee1eSDan Willemsen				{K: text.ListOpen},
949*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Enum{"TRUE"}}},
950*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Enum{"FALSE"}}},
951*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Enum{"T"}}},
952*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Enum{"F"}}},
953*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Enum{"t"}}},
954*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Enum{"f"}}},
955*1c12ee1eSDan Willemsen				{K: text.ListClose},
956*1c12ee1eSDan Willemsen			},
957*1c12ee1eSDan Willemsen		},
958*1c12ee1eSDan Willemsen		{
959*1c12ee1eSDan Willemsen			in: `foo: Enum1[bar]:Enum2`,
960*1c12ee1eSDan Willemsen			want: []R{
961*1c12ee1eSDan Willemsen				{K: text.Name},
962*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Enum{"Enum1"}}},
963*1c12ee1eSDan Willemsen				{K: text.Name},
964*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Enum{"Enum2"}}},
965*1c12ee1eSDan Willemsen			},
966*1c12ee1eSDan Willemsen		},
967*1c12ee1eSDan Willemsen		{
968*1c12ee1eSDan Willemsen			// Invalid enum values.
969*1c12ee1eSDan Willemsen			in: `name: [-inf, -foo, "string", 42, 1.0, 0x47]`,
970*1c12ee1eSDan Willemsen			want: []R{
971*1c12ee1eSDan Willemsen				{K: text.Name},
972*1c12ee1eSDan Willemsen				{K: text.ListOpen},
973*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{nok: Enum{}}},
974*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{nok: Enum{}}},
975*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{nok: Enum{}}},
976*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{nok: Enum{}}},
977*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{nok: Enum{}}},
978*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{nok: Enum{}}},
979*1c12ee1eSDan Willemsen				{K: text.ListClose},
980*1c12ee1eSDan Willemsen			},
981*1c12ee1eSDan Willemsen		},
982*1c12ee1eSDan Willemsen		{
983*1c12ee1eSDan Willemsen			in: `name: true.`,
984*1c12ee1eSDan Willemsen			want: []R{
985*1c12ee1eSDan Willemsen				{K: text.Name},
986*1c12ee1eSDan Willemsen				{E: `invalid scalar value: true.`},
987*1c12ee1eSDan Willemsen			},
988*1c12ee1eSDan Willemsen		},
989*1c12ee1eSDan Willemsen
990*1c12ee1eSDan Willemsen		// Numeric values.
991*1c12ee1eSDan Willemsen		{
992*1c12ee1eSDan Willemsen			in: `nums:42 nums:0x2A nums:052`,
993*1c12ee1eSDan Willemsen			want: []R{
994*1c12ee1eSDan Willemsen				{K: text.Name},
995*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Uint64{42}}},
996*1c12ee1eSDan Willemsen				{K: text.Name},
997*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Uint64{42}}},
998*1c12ee1eSDan Willemsen				{K: text.Name},
999*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Uint64{42}}},
1000*1c12ee1eSDan Willemsen			},
1001*1c12ee1eSDan Willemsen		},
1002*1c12ee1eSDan Willemsen		{
1003*1c12ee1eSDan Willemsen			in: `nums:[-42, -0x2a, -052]`,
1004*1c12ee1eSDan Willemsen			want: []R{
1005*1c12ee1eSDan Willemsen				{K: text.Name},
1006*1c12ee1eSDan Willemsen				{K: text.ListOpen},
1007*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{nok: Uint64{}}},
1008*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{nok: Uint64{}}},
1009*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{nok: Uint64{}}},
1010*1c12ee1eSDan Willemsen				{K: text.ListClose},
1011*1c12ee1eSDan Willemsen			},
1012*1c12ee1eSDan Willemsen		},
1013*1c12ee1eSDan Willemsen		{
1014*1c12ee1eSDan Willemsen			in: `nums:[-42, -0x2a, -052]`,
1015*1c12ee1eSDan Willemsen			want: []R{
1016*1c12ee1eSDan Willemsen				{K: text.Name},
1017*1c12ee1eSDan Willemsen				{K: text.ListOpen},
1018*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Int64{-42}}},
1019*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Int64{-42}}},
1020*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Int64{-42}}},
1021*1c12ee1eSDan Willemsen				{K: text.ListClose},
1022*1c12ee1eSDan Willemsen			},
1023*1c12ee1eSDan Willemsen		},
1024*1c12ee1eSDan Willemsen		{
1025*1c12ee1eSDan Willemsen			in: `nums: [0,0x0,00,-9876543210,9876543210,0x0123456789abcdef,-0x0123456789abcdef,01234567,-01234567]`,
1026*1c12ee1eSDan Willemsen			want: []R{
1027*1c12ee1eSDan Willemsen				{K: text.Name},
1028*1c12ee1eSDan Willemsen				{K: text.ListOpen},
1029*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Uint64{0}}},
1030*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Int64{0}}},
1031*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Uint64{0}}},
1032*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Int64{-9876543210}}},
1033*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Uint64{9876543210}}},
1034*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Uint64{0x0123456789abcdef}}},
1035*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Int64{-0x0123456789abcdef}}},
1036*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Uint64{01234567}}},
1037*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Int64{-01234567}}},
1038*1c12ee1eSDan Willemsen				{K: text.ListClose},
1039*1c12ee1eSDan Willemsen			},
1040*1c12ee1eSDan Willemsen		},
1041*1c12ee1eSDan Willemsen		{
1042*1c12ee1eSDan Willemsen			in: `nums: [0,0x0,00,-876543210,876543210,0x01234,-0x01234,01234567,-01234567]`,
1043*1c12ee1eSDan Willemsen			want: []R{
1044*1c12ee1eSDan Willemsen				{K: text.Name},
1045*1c12ee1eSDan Willemsen				{K: text.ListOpen},
1046*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Uint32{0}}},
1047*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Int32{0}}},
1048*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Uint32{0}}},
1049*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Int32{-876543210}}},
1050*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Uint32{876543210}}},
1051*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Uint32{0x01234}}},
1052*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Int32{-0x01234}}},
1053*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Uint32{01234567}}},
1054*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Int32{-01234567}}},
1055*1c12ee1eSDan Willemsen				{K: text.ListClose},
1056*1c12ee1eSDan Willemsen			},
1057*1c12ee1eSDan Willemsen		},
1058*1c12ee1eSDan Willemsen		{
1059*1c12ee1eSDan Willemsen			in: `nums: [` +
1060*1c12ee1eSDan Willemsen				fmt.Sprintf("%d", uint64(math.MaxUint64)) + `,` +
1061*1c12ee1eSDan Willemsen				fmt.Sprintf("%d", uint32(math.MaxUint32)) + `,` +
1062*1c12ee1eSDan Willemsen				fmt.Sprintf("%d", int64(math.MaxInt64)) + `,` +
1063*1c12ee1eSDan Willemsen				fmt.Sprintf("%d", int64(math.MinInt64)) + `,` +
1064*1c12ee1eSDan Willemsen				fmt.Sprintf("%d", int32(math.MaxInt32)) + `,` +
1065*1c12ee1eSDan Willemsen				fmt.Sprintf("%d", int32(math.MinInt32)) +
1066*1c12ee1eSDan Willemsen				`]`,
1067*1c12ee1eSDan Willemsen			want: []R{
1068*1c12ee1eSDan Willemsen				{K: text.Name},
1069*1c12ee1eSDan Willemsen				{K: text.ListOpen},
1070*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Uint64{math.MaxUint64}}},
1071*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Uint32{math.MaxUint32}}},
1072*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Int64{math.MaxInt64}}},
1073*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Int64{math.MinInt64}}},
1074*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Int32{math.MaxInt32}}},
1075*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Int32{math.MinInt32}}},
1076*1c12ee1eSDan Willemsen				{K: text.ListClose},
1077*1c12ee1eSDan Willemsen			},
1078*1c12ee1eSDan Willemsen		},
1079*1c12ee1eSDan Willemsen		{
1080*1c12ee1eSDan Willemsen			// Integer exceeds range.
1081*1c12ee1eSDan Willemsen			in: `nums: [` +
1082*1c12ee1eSDan Willemsen				`18446744073709551616,` + // max uint64 + 1
1083*1c12ee1eSDan Willemsen				fmt.Sprintf("%d", uint64(math.MaxUint32+1)) + `,` +
1084*1c12ee1eSDan Willemsen				fmt.Sprintf("%d", uint64(math.MaxInt64+1)) + `,` +
1085*1c12ee1eSDan Willemsen				`-9223372036854775809,` + // min int64 - 1
1086*1c12ee1eSDan Willemsen				fmt.Sprintf("%d", uint64(math.MaxInt32+1)) + `,` +
1087*1c12ee1eSDan Willemsen				fmt.Sprintf("%d", int64(math.MinInt32-1)) + `` +
1088*1c12ee1eSDan Willemsen				`]`,
1089*1c12ee1eSDan Willemsen			want: []R{
1090*1c12ee1eSDan Willemsen				{K: text.Name},
1091*1c12ee1eSDan Willemsen				{K: text.ListOpen},
1092*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{nok: Uint64{}}},
1093*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{nok: Uint32{}}},
1094*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{nok: Int64{}}},
1095*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{nok: Int64{}}},
1096*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{nok: Int32{}}},
1097*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{nok: Int32{}}},
1098*1c12ee1eSDan Willemsen				{K: text.ListClose},
1099*1c12ee1eSDan Willemsen			},
1100*1c12ee1eSDan Willemsen		},
1101*1c12ee1eSDan Willemsen		{
1102*1c12ee1eSDan Willemsen			in: `nums: [0xbeefbeef, 0xbeefbeefbeefbeef]`,
1103*1c12ee1eSDan Willemsen			want: []R{
1104*1c12ee1eSDan Willemsen				{K: text.Name},
1105*1c12ee1eSDan Willemsen				{K: text.ListOpen},
1106*1c12ee1eSDan Willemsen				{
1107*1c12ee1eSDan Willemsen					K: text.Scalar,
1108*1c12ee1eSDan Willemsen					T: func() ST {
1109*1c12ee1eSDan Willemsen						if flags.ProtoLegacy {
1110*1c12ee1eSDan Willemsen							return ST{ok: Int32{-1091584273}}
1111*1c12ee1eSDan Willemsen						}
1112*1c12ee1eSDan Willemsen						return ST{nok: Int32{}}
1113*1c12ee1eSDan Willemsen					}(),
1114*1c12ee1eSDan Willemsen				},
1115*1c12ee1eSDan Willemsen				{
1116*1c12ee1eSDan Willemsen					K: text.Scalar,
1117*1c12ee1eSDan Willemsen					T: func() ST {
1118*1c12ee1eSDan Willemsen						if flags.ProtoLegacy {
1119*1c12ee1eSDan Willemsen							return ST{ok: Int64{-4688318750159552785}}
1120*1c12ee1eSDan Willemsen						}
1121*1c12ee1eSDan Willemsen						return ST{nok: Int64{}}
1122*1c12ee1eSDan Willemsen					}(),
1123*1c12ee1eSDan Willemsen				},
1124*1c12ee1eSDan Willemsen				{K: text.ListClose},
1125*1c12ee1eSDan Willemsen			},
1126*1c12ee1eSDan Willemsen		},
1127*1c12ee1eSDan Willemsen		{
1128*1c12ee1eSDan Willemsen			in: `nums: [0.,0f,1f,10f,-0f,-1f,-10f,1.0,0.1e-3,1.5e+5,1e10,.0]`,
1129*1c12ee1eSDan Willemsen			want: []R{
1130*1c12ee1eSDan Willemsen				{K: text.Name},
1131*1c12ee1eSDan Willemsen				{K: text.ListOpen},
1132*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Float64{0.0}}},
1133*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Float64{0.0}}},
1134*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Float64{1.0}}},
1135*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Float64{10.0}}},
1136*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Float64{math.Copysign(0, -1)}}},
1137*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Float64{-1.0}}},
1138*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Float64{-10.0}}},
1139*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Float64{1.0}}},
1140*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Float64{0.1e-3}}},
1141*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Float64{1.5e+5}}},
1142*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Float64{1.0e+10}}},
1143*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Float64{0.0}}},
1144*1c12ee1eSDan Willemsen				{K: text.ListClose},
1145*1c12ee1eSDan Willemsen			},
1146*1c12ee1eSDan Willemsen		},
1147*1c12ee1eSDan Willemsen		{
1148*1c12ee1eSDan Willemsen			in: `nums: [0.,0f,1f,10f,-0f,-1f,-10f,1.0,0.1e-3,1.5e+5,1e10,.0]`,
1149*1c12ee1eSDan Willemsen			want: []R{
1150*1c12ee1eSDan Willemsen				{K: text.Name},
1151*1c12ee1eSDan Willemsen				{K: text.ListOpen},
1152*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Float32{0.0}}},
1153*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Float32{0.0}}},
1154*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Float32{1.0}}},
1155*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Float32{10.0}}},
1156*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Float32{float32(math.Copysign(0, -1))}}},
1157*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Float32{-1.0}}},
1158*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Float32{-10.0}}},
1159*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Float32{1.0}}},
1160*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Float32{0.1e-3}}},
1161*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Float32{1.5e+5}}},
1162*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Float32{1.0e+10}}},
1163*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Float32{0.0}}},
1164*1c12ee1eSDan Willemsen				{K: text.ListClose},
1165*1c12ee1eSDan Willemsen			},
1166*1c12ee1eSDan Willemsen		},
1167*1c12ee1eSDan Willemsen		{
1168*1c12ee1eSDan Willemsen			in: `nums: [0.,1f,10F,1e1,1.10]`,
1169*1c12ee1eSDan Willemsen			want: []R{
1170*1c12ee1eSDan Willemsen				{K: text.Name},
1171*1c12ee1eSDan Willemsen				{K: text.ListOpen},
1172*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{nok: Int64{}}},
1173*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{nok: Int64{}}},
1174*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{nok: Int64{}}},
1175*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{nok: Int64{}}},
1176*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{nok: Int64{}}},
1177*1c12ee1eSDan Willemsen				{K: text.ListClose},
1178*1c12ee1eSDan Willemsen			},
1179*1c12ee1eSDan Willemsen		},
1180*1c12ee1eSDan Willemsen		{
1181*1c12ee1eSDan Willemsen			in: `nums: [0.,1f,10F,1e1,1.10]`,
1182*1c12ee1eSDan Willemsen			want: []R{
1183*1c12ee1eSDan Willemsen				{K: text.Name},
1184*1c12ee1eSDan Willemsen				{K: text.ListOpen},
1185*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{nok: Int32{}}},
1186*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{nok: Int32{}}},
1187*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{nok: Int32{}}},
1188*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{nok: Int32{}}},
1189*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{nok: Int32{}}},
1190*1c12ee1eSDan Willemsen				{K: text.ListClose},
1191*1c12ee1eSDan Willemsen			},
1192*1c12ee1eSDan Willemsen		},
1193*1c12ee1eSDan Willemsen		{
1194*1c12ee1eSDan Willemsen			in: `nums: [0.,1f,10F,1e1,1.10]`,
1195*1c12ee1eSDan Willemsen			want: []R{
1196*1c12ee1eSDan Willemsen				{K: text.Name},
1197*1c12ee1eSDan Willemsen				{K: text.ListOpen},
1198*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{nok: Uint64{}}},
1199*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{nok: Uint64{}}},
1200*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{nok: Uint64{}}},
1201*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{nok: Uint64{}}},
1202*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{nok: Uint64{}}},
1203*1c12ee1eSDan Willemsen				{K: text.ListClose},
1204*1c12ee1eSDan Willemsen			},
1205*1c12ee1eSDan Willemsen		},
1206*1c12ee1eSDan Willemsen		{
1207*1c12ee1eSDan Willemsen			in: `nums: [0.,1f,10F,1e1,1.10]`,
1208*1c12ee1eSDan Willemsen			want: []R{
1209*1c12ee1eSDan Willemsen				{K: text.Name},
1210*1c12ee1eSDan Willemsen				{K: text.ListOpen},
1211*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{nok: Uint32{}}},
1212*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{nok: Uint32{}}},
1213*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{nok: Uint32{}}},
1214*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{nok: Uint32{}}},
1215*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{nok: Uint32{}}},
1216*1c12ee1eSDan Willemsen				{K: text.ListClose},
1217*1c12ee1eSDan Willemsen			},
1218*1c12ee1eSDan Willemsen		},
1219*1c12ee1eSDan Willemsen		{
1220*1c12ee1eSDan Willemsen			in: `nums: [` +
1221*1c12ee1eSDan Willemsen				fmt.Sprintf("%g", math.MaxFloat32) + `,` +
1222*1c12ee1eSDan Willemsen				fmt.Sprintf("%g", -math.MaxFloat32) + `,` +
1223*1c12ee1eSDan Willemsen				fmt.Sprintf("%g", math.MaxFloat32*2) + `,` +
1224*1c12ee1eSDan Willemsen				fmt.Sprintf("%g", -math.MaxFloat32*2) + `,` +
1225*1c12ee1eSDan Willemsen				`3.59539e+308,` + // math.MaxFloat64 * 2
1226*1c12ee1eSDan Willemsen				`-3.59539e+308,` + // -math.MaxFloat64 * 2
1227*1c12ee1eSDan Willemsen				fmt.Sprintf("%d000", uint64(math.MaxUint64)) +
1228*1c12ee1eSDan Willemsen				`]`,
1229*1c12ee1eSDan Willemsen			want: []R{
1230*1c12ee1eSDan Willemsen				{K: text.Name},
1231*1c12ee1eSDan Willemsen				{K: text.ListOpen},
1232*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Float32{float32(math.MaxFloat32)}}},
1233*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Float32{float32(-math.MaxFloat32)}}},
1234*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Float32{float32(math.Inf(1))}}},
1235*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Float32{float32(math.Inf(-1))}}},
1236*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Float32{float32(math.Inf(1))}}},
1237*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Float32{float32(math.Inf(-1))}}},
1238*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Float32{float32(math.MaxUint64) * 1000}}},
1239*1c12ee1eSDan Willemsen				{K: text.ListClose},
1240*1c12ee1eSDan Willemsen			},
1241*1c12ee1eSDan Willemsen		},
1242*1c12ee1eSDan Willemsen		{
1243*1c12ee1eSDan Willemsen			in: `nums: [` +
1244*1c12ee1eSDan Willemsen				fmt.Sprintf("%g", math.MaxFloat64) + `,` +
1245*1c12ee1eSDan Willemsen				fmt.Sprintf("%g", -math.MaxFloat64) + `,` +
1246*1c12ee1eSDan Willemsen				`3.59539e+308,` + // math.MaxFloat64 * 2
1247*1c12ee1eSDan Willemsen				`-3.59539e+308,` + // -math.MaxFloat64 * 2
1248*1c12ee1eSDan Willemsen				fmt.Sprintf("%d000", uint64(math.MaxUint64)) +
1249*1c12ee1eSDan Willemsen				`]`,
1250*1c12ee1eSDan Willemsen			want: []R{
1251*1c12ee1eSDan Willemsen				{K: text.Name},
1252*1c12ee1eSDan Willemsen				{K: text.ListOpen},
1253*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Float64{math.MaxFloat64}}},
1254*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Float64{-math.MaxFloat64}}},
1255*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Float64{math.Inf(1)}}},
1256*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Float64{math.Inf(-1)}}},
1257*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Float64{float64(math.MaxUint64) * 1000}}},
1258*1c12ee1eSDan Willemsen				{K: text.ListClose},
1259*1c12ee1eSDan Willemsen			},
1260*1c12ee1eSDan Willemsen		},
1261*1c12ee1eSDan Willemsen		{
1262*1c12ee1eSDan Willemsen			// -0 is only valid for signed types. It is not valid for unsigned types.
1263*1c12ee1eSDan Willemsen			in: `num: [-0, -0]`,
1264*1c12ee1eSDan Willemsen			want: []R{
1265*1c12ee1eSDan Willemsen				{K: text.Name},
1266*1c12ee1eSDan Willemsen				{K: text.ListOpen},
1267*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{nok: Uint32{}}},
1268*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{nok: Uint64{}}},
1269*1c12ee1eSDan Willemsen				{K: text.ListClose},
1270*1c12ee1eSDan Willemsen			},
1271*1c12ee1eSDan Willemsen		},
1272*1c12ee1eSDan Willemsen		{
1273*1c12ee1eSDan Willemsen			// -0 is only valid for signed types. It is not valid for unsigned types.
1274*1c12ee1eSDan Willemsen			in: `num: [-0, -0]`,
1275*1c12ee1eSDan Willemsen			want: []R{
1276*1c12ee1eSDan Willemsen				{K: text.Name},
1277*1c12ee1eSDan Willemsen				{K: text.ListOpen},
1278*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Int32{0}}},
1279*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Int64{0}}},
1280*1c12ee1eSDan Willemsen				{K: text.ListClose},
1281*1c12ee1eSDan Willemsen			},
1282*1c12ee1eSDan Willemsen		},
1283*1c12ee1eSDan Willemsen		{
1284*1c12ee1eSDan Willemsen			// Negative zeros on float64 should preserve sign bit.
1285*1c12ee1eSDan Willemsen			in: `num: [-0, -.0]`,
1286*1c12ee1eSDan Willemsen			want: []R{
1287*1c12ee1eSDan Willemsen				{K: text.Name},
1288*1c12ee1eSDan Willemsen				{K: text.ListOpen},
1289*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Float64{math.Copysign(0, -1)}}},
1290*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Float64{math.Copysign(0, -1)}}},
1291*1c12ee1eSDan Willemsen				{K: text.ListClose},
1292*1c12ee1eSDan Willemsen			},
1293*1c12ee1eSDan Willemsen		},
1294*1c12ee1eSDan Willemsen		{
1295*1c12ee1eSDan Willemsen			// Negative zeros on float32 should preserve sign bit.
1296*1c12ee1eSDan Willemsen			in: `num: [-0, -.0]`,
1297*1c12ee1eSDan Willemsen			want: []R{
1298*1c12ee1eSDan Willemsen				{K: text.Name},
1299*1c12ee1eSDan Willemsen				{K: text.ListOpen},
1300*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Float32{float32(math.Copysign(0, -1))}}},
1301*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Float32{float32(math.Copysign(0, -1))}}},
1302*1c12ee1eSDan Willemsen				{K: text.ListClose},
1303*1c12ee1eSDan Willemsen			},
1304*1c12ee1eSDan Willemsen		},
1305*1c12ee1eSDan Willemsen		{
1306*1c12ee1eSDan Willemsen			in: `num: +0`,
1307*1c12ee1eSDan Willemsen			want: []R{
1308*1c12ee1eSDan Willemsen				{K: text.Name},
1309*1c12ee1eSDan Willemsen				{E: `invalid scalar value: +`},
1310*1c12ee1eSDan Willemsen			},
1311*1c12ee1eSDan Willemsen		},
1312*1c12ee1eSDan Willemsen		{
1313*1c12ee1eSDan Willemsen			in: `num: 01.1234`,
1314*1c12ee1eSDan Willemsen			want: []R{
1315*1c12ee1eSDan Willemsen				{K: text.Name},
1316*1c12ee1eSDan Willemsen				{E: `invalid scalar value: 01.1234`},
1317*1c12ee1eSDan Willemsen			},
1318*1c12ee1eSDan Willemsen		},
1319*1c12ee1eSDan Willemsen		{
1320*1c12ee1eSDan Willemsen			in: `num: 0x`,
1321*1c12ee1eSDan Willemsen			want: []R{
1322*1c12ee1eSDan Willemsen				{K: text.Name},
1323*1c12ee1eSDan Willemsen				{E: `invalid scalar value: 0x`},
1324*1c12ee1eSDan Willemsen			},
1325*1c12ee1eSDan Willemsen		},
1326*1c12ee1eSDan Willemsen		{
1327*1c12ee1eSDan Willemsen			in: `num: 0xX`,
1328*1c12ee1eSDan Willemsen			want: []R{
1329*1c12ee1eSDan Willemsen				{K: text.Name},
1330*1c12ee1eSDan Willemsen				{E: `invalid scalar value: 0xX`},
1331*1c12ee1eSDan Willemsen			},
1332*1c12ee1eSDan Willemsen		},
1333*1c12ee1eSDan Willemsen		{
1334*1c12ee1eSDan Willemsen			in: `num: 0800`,
1335*1c12ee1eSDan Willemsen			want: []R{
1336*1c12ee1eSDan Willemsen				{K: text.Name},
1337*1c12ee1eSDan Willemsen				{E: `invalid scalar value: 0800`},
1338*1c12ee1eSDan Willemsen			},
1339*1c12ee1eSDan Willemsen		},
1340*1c12ee1eSDan Willemsen		{
1341*1c12ee1eSDan Willemsen			in: `num: 1.`,
1342*1c12ee1eSDan Willemsen			want: []R{
1343*1c12ee1eSDan Willemsen				{K: text.Name},
1344*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Float32{1.0}}},
1345*1c12ee1eSDan Willemsen			},
1346*1c12ee1eSDan Willemsen		},
1347*1c12ee1eSDan Willemsen		{
1348*1c12ee1eSDan Willemsen			in: `num: -.`,
1349*1c12ee1eSDan Willemsen			want: []R{
1350*1c12ee1eSDan Willemsen				{K: text.Name},
1351*1c12ee1eSDan Willemsen				{E: `invalid scalar value: -.`},
1352*1c12ee1eSDan Willemsen			},
1353*1c12ee1eSDan Willemsen		},
1354*1c12ee1eSDan Willemsen
1355*1c12ee1eSDan Willemsen		// Float special literal values, case-insensitive match.
1356*1c12ee1eSDan Willemsen		{
1357*1c12ee1eSDan Willemsen			in: `name:[nan, NaN, Nan, NAN]`,
1358*1c12ee1eSDan Willemsen			want: []R{
1359*1c12ee1eSDan Willemsen				{K: text.Name},
1360*1c12ee1eSDan Willemsen				{K: text.ListOpen},
1361*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Float64{math.NaN()}}},
1362*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Float64{math.NaN()}}},
1363*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Float64{math.NaN()}}},
1364*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Float64{math.NaN()}}},
1365*1c12ee1eSDan Willemsen				{K: text.ListClose},
1366*1c12ee1eSDan Willemsen			},
1367*1c12ee1eSDan Willemsen		},
1368*1c12ee1eSDan Willemsen		{
1369*1c12ee1eSDan Willemsen			in: `name:[inf, INF, infinity, Infinity, INFinity]`,
1370*1c12ee1eSDan Willemsen			want: []R{
1371*1c12ee1eSDan Willemsen				{K: text.Name},
1372*1c12ee1eSDan Willemsen				{K: text.ListOpen},
1373*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Float64{math.Inf(1)}}},
1374*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Float64{math.Inf(1)}}},
1375*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Float64{math.Inf(1)}}},
1376*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Float64{math.Inf(1)}}},
1377*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Float64{math.Inf(1)}}},
1378*1c12ee1eSDan Willemsen				{K: text.ListClose},
1379*1c12ee1eSDan Willemsen			},
1380*1c12ee1eSDan Willemsen		},
1381*1c12ee1eSDan Willemsen		{
1382*1c12ee1eSDan Willemsen			in: `name:[-inf, -INF, -infinity, -Infinity, -INFinity]`,
1383*1c12ee1eSDan Willemsen			want: []R{
1384*1c12ee1eSDan Willemsen				{K: text.Name},
1385*1c12ee1eSDan Willemsen				{K: text.ListOpen},
1386*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Float64{math.Inf(-1)}}},
1387*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Float64{math.Inf(-1)}}},
1388*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Float64{math.Inf(-1)}}},
1389*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Float64{math.Inf(-1)}}},
1390*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Float64{math.Inf(-1)}}},
1391*1c12ee1eSDan Willemsen				{K: text.ListClose},
1392*1c12ee1eSDan Willemsen			},
1393*1c12ee1eSDan Willemsen		},
1394*1c12ee1eSDan Willemsen		{
1395*1c12ee1eSDan Willemsen			in: `name:[nan, NaN, Nan, NAN]`,
1396*1c12ee1eSDan Willemsen			want: []R{
1397*1c12ee1eSDan Willemsen				{K: text.Name},
1398*1c12ee1eSDan Willemsen				{K: text.ListOpen},
1399*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Float32{float32(math.NaN())}}},
1400*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Float32{float32(math.NaN())}}},
1401*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Float32{float32(math.NaN())}}},
1402*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Float32{float32(math.NaN())}}},
1403*1c12ee1eSDan Willemsen				{K: text.ListClose},
1404*1c12ee1eSDan Willemsen			},
1405*1c12ee1eSDan Willemsen		},
1406*1c12ee1eSDan Willemsen		{
1407*1c12ee1eSDan Willemsen			in: `name:[inf, INF, infinity, Infinity, INFinity]`,
1408*1c12ee1eSDan Willemsen			want: []R{
1409*1c12ee1eSDan Willemsen				{K: text.Name},
1410*1c12ee1eSDan Willemsen				{K: text.ListOpen},
1411*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Float32{float32(math.Inf(1))}}},
1412*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Float32{float32(math.Inf(1))}}},
1413*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Float32{float32(math.Inf(1))}}},
1414*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Float32{float32(math.Inf(1))}}},
1415*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Float32{float32(math.Inf(1))}}},
1416*1c12ee1eSDan Willemsen				{K: text.ListClose},
1417*1c12ee1eSDan Willemsen			},
1418*1c12ee1eSDan Willemsen		},
1419*1c12ee1eSDan Willemsen		{
1420*1c12ee1eSDan Willemsen			in: `name:[-inf, -INF, -infinity, -Infinity, -INFinity]`,
1421*1c12ee1eSDan Willemsen			want: []R{
1422*1c12ee1eSDan Willemsen				{K: text.Name},
1423*1c12ee1eSDan Willemsen				{K: text.ListOpen},
1424*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Float32{float32(math.Inf(-1))}}},
1425*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Float32{float32(math.Inf(-1))}}},
1426*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Float32{float32(math.Inf(-1))}}},
1427*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Float32{float32(math.Inf(-1))}}},
1428*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Float32{float32(math.Inf(-1))}}},
1429*1c12ee1eSDan Willemsen				{K: text.ListClose},
1430*1c12ee1eSDan Willemsen			},
1431*1c12ee1eSDan Willemsen		},
1432*1c12ee1eSDan Willemsen		{
1433*1c12ee1eSDan Willemsen			// C++ permits this, but we currently reject this. It is easy to add
1434*1c12ee1eSDan Willemsen			// if needed.
1435*1c12ee1eSDan Willemsen			in: `name: -nan`,
1436*1c12ee1eSDan Willemsen			want: []R{
1437*1c12ee1eSDan Willemsen				{K: text.Name},
1438*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{nok: Float64{}}},
1439*1c12ee1eSDan Willemsen			},
1440*1c12ee1eSDan Willemsen		},
1441*1c12ee1eSDan Willemsen		// Messages.
1442*1c12ee1eSDan Willemsen		{
1443*1c12ee1eSDan Willemsen			in: `m: {}`,
1444*1c12ee1eSDan Willemsen			want: []R{
1445*1c12ee1eSDan Willemsen				{K: text.Name},
1446*1c12ee1eSDan Willemsen				{K: text.MessageOpen},
1447*1c12ee1eSDan Willemsen				{K: text.MessageClose},
1448*1c12ee1eSDan Willemsen				{K: text.EOF},
1449*1c12ee1eSDan Willemsen			},
1450*1c12ee1eSDan Willemsen		},
1451*1c12ee1eSDan Willemsen		{
1452*1c12ee1eSDan Willemsen			in: `m: <>`,
1453*1c12ee1eSDan Willemsen			want: []R{
1454*1c12ee1eSDan Willemsen				{K: text.Name},
1455*1c12ee1eSDan Willemsen				{K: text.MessageOpen},
1456*1c12ee1eSDan Willemsen				{K: text.MessageClose},
1457*1c12ee1eSDan Willemsen				{K: text.EOF},
1458*1c12ee1eSDan Willemsen			},
1459*1c12ee1eSDan Willemsen		},
1460*1c12ee1eSDan Willemsen		{
1461*1c12ee1eSDan Willemsen			in: space + `m {` + space + "\n# comment\n" + `}` + space,
1462*1c12ee1eSDan Willemsen			want: []R{
1463*1c12ee1eSDan Willemsen				{K: text.Name},
1464*1c12ee1eSDan Willemsen				{K: text.MessageOpen},
1465*1c12ee1eSDan Willemsen				{K: text.MessageClose},
1466*1c12ee1eSDan Willemsen			},
1467*1c12ee1eSDan Willemsen		},
1468*1c12ee1eSDan Willemsen		{
1469*1c12ee1eSDan Willemsen			in: `m { foo: < bar: "hello" > }`,
1470*1c12ee1eSDan Willemsen			want: []R{
1471*1c12ee1eSDan Willemsen				{K: text.Name, RS: "m"},
1472*1c12ee1eSDan Willemsen				{K: text.MessageOpen},
1473*1c12ee1eSDan Willemsen
1474*1c12ee1eSDan Willemsen				{K: text.Name, RS: "foo"},
1475*1c12ee1eSDan Willemsen				{K: text.MessageOpen},
1476*1c12ee1eSDan Willemsen
1477*1c12ee1eSDan Willemsen				{K: text.Name, RS: "bar"},
1478*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Str{"hello"}}},
1479*1c12ee1eSDan Willemsen
1480*1c12ee1eSDan Willemsen				{K: text.MessageClose},
1481*1c12ee1eSDan Willemsen
1482*1c12ee1eSDan Willemsen				{K: text.MessageClose},
1483*1c12ee1eSDan Willemsen			},
1484*1c12ee1eSDan Willemsen		},
1485*1c12ee1eSDan Willemsen		{
1486*1c12ee1eSDan Willemsen			in: `list [ <s:"hello">, {s:"world"} ]`,
1487*1c12ee1eSDan Willemsen			want: []R{
1488*1c12ee1eSDan Willemsen				{K: text.Name, RS: "list"},
1489*1c12ee1eSDan Willemsen				{K: text.ListOpen},
1490*1c12ee1eSDan Willemsen
1491*1c12ee1eSDan Willemsen				{K: text.MessageOpen},
1492*1c12ee1eSDan Willemsen				{K: text.Name, RS: "s"},
1493*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Str{"hello"}}},
1494*1c12ee1eSDan Willemsen				{K: text.MessageClose},
1495*1c12ee1eSDan Willemsen
1496*1c12ee1eSDan Willemsen				{K: text.MessageOpen},
1497*1c12ee1eSDan Willemsen				{K: text.Name, RS: "s"},
1498*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Str{"world"}}},
1499*1c12ee1eSDan Willemsen				{K: text.MessageClose},
1500*1c12ee1eSDan Willemsen
1501*1c12ee1eSDan Willemsen				{K: text.ListClose},
1502*1c12ee1eSDan Willemsen				{K: text.EOF},
1503*1c12ee1eSDan Willemsen			},
1504*1c12ee1eSDan Willemsen		},
1505*1c12ee1eSDan Willemsen		{
1506*1c12ee1eSDan Willemsen			in: `m: { >`,
1507*1c12ee1eSDan Willemsen			want: []R{
1508*1c12ee1eSDan Willemsen				{K: text.Name},
1509*1c12ee1eSDan Willemsen				{K: text.MessageOpen},
1510*1c12ee1eSDan Willemsen				{E: `mismatched close character '>'`},
1511*1c12ee1eSDan Willemsen			},
1512*1c12ee1eSDan Willemsen		},
1513*1c12ee1eSDan Willemsen		{
1514*1c12ee1eSDan Willemsen			in: `m: <s: "hello"}`,
1515*1c12ee1eSDan Willemsen			want: []R{
1516*1c12ee1eSDan Willemsen				{K: text.Name},
1517*1c12ee1eSDan Willemsen				{K: text.MessageOpen},
1518*1c12ee1eSDan Willemsen
1519*1c12ee1eSDan Willemsen				{K: text.Name},
1520*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Str{"hello"}}},
1521*1c12ee1eSDan Willemsen
1522*1c12ee1eSDan Willemsen				{E: `mismatched close character '}'`},
1523*1c12ee1eSDan Willemsen			},
1524*1c12ee1eSDan Willemsen		},
1525*1c12ee1eSDan Willemsen		{
1526*1c12ee1eSDan Willemsen			in:   `{}`,
1527*1c12ee1eSDan Willemsen			want: []R{{E: `invalid field name: {`}},
1528*1c12ee1eSDan Willemsen		},
1529*1c12ee1eSDan Willemsen		{
1530*1c12ee1eSDan Willemsen			in: `
1531*1c12ee1eSDan Willemsenm: {
1532*1c12ee1eSDan Willemsen  foo: true;
1533*1c12ee1eSDan Willemsen  bar: {
1534*1c12ee1eSDan Willemsen	enum: ENUM
1535*1c12ee1eSDan Willemsen	list: [ < >, { } ] ;
1536*1c12ee1eSDan Willemsen  }
1537*1c12ee1eSDan Willemsen  [qux]: "end"
1538*1c12ee1eSDan Willemsen}
1539*1c12ee1eSDan Willemsen				`,
1540*1c12ee1eSDan Willemsen			want: []R{
1541*1c12ee1eSDan Willemsen				{K: text.Name},
1542*1c12ee1eSDan Willemsen				{K: text.MessageOpen},
1543*1c12ee1eSDan Willemsen
1544*1c12ee1eSDan Willemsen				{K: text.Name, RS: "foo"},
1545*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Bool{true}}},
1546*1c12ee1eSDan Willemsen
1547*1c12ee1eSDan Willemsen				{K: text.Name, RS: "bar"},
1548*1c12ee1eSDan Willemsen				{K: text.MessageOpen},
1549*1c12ee1eSDan Willemsen
1550*1c12ee1eSDan Willemsen				{K: text.Name, RS: "enum"},
1551*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Enum{"ENUM"}}},
1552*1c12ee1eSDan Willemsen
1553*1c12ee1eSDan Willemsen				{K: text.Name, RS: "list"},
1554*1c12ee1eSDan Willemsen				{K: text.ListOpen},
1555*1c12ee1eSDan Willemsen				{K: text.MessageOpen},
1556*1c12ee1eSDan Willemsen				{K: text.MessageClose},
1557*1c12ee1eSDan Willemsen				{K: text.MessageOpen},
1558*1c12ee1eSDan Willemsen				{K: text.MessageClose},
1559*1c12ee1eSDan Willemsen				{K: text.ListClose},
1560*1c12ee1eSDan Willemsen
1561*1c12ee1eSDan Willemsen				{K: text.MessageClose},
1562*1c12ee1eSDan Willemsen
1563*1c12ee1eSDan Willemsen				{K: text.Name, RS: "[qux]"},
1564*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Str{"end"}}},
1565*1c12ee1eSDan Willemsen
1566*1c12ee1eSDan Willemsen				{K: text.MessageClose},
1567*1c12ee1eSDan Willemsen				{K: text.EOF},
1568*1c12ee1eSDan Willemsen			},
1569*1c12ee1eSDan Willemsen		},
1570*1c12ee1eSDan Willemsen
1571*1c12ee1eSDan Willemsen		// Other syntax errors.
1572*1c12ee1eSDan Willemsen		{
1573*1c12ee1eSDan Willemsen			in: "x: -",
1574*1c12ee1eSDan Willemsen			want: []R{
1575*1c12ee1eSDan Willemsen				{K: text.Name},
1576*1c12ee1eSDan Willemsen				{E: `syntax error (line 1:4): invalid scalar value: -`},
1577*1c12ee1eSDan Willemsen			},
1578*1c12ee1eSDan Willemsen		},
1579*1c12ee1eSDan Willemsen		{
1580*1c12ee1eSDan Willemsen			in: "x:[\"��\"x",
1581*1c12ee1eSDan Willemsen			want: []R{
1582*1c12ee1eSDan Willemsen				{K: text.Name},
1583*1c12ee1eSDan Willemsen				{K: text.ListOpen},
1584*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Str{"��"}}, P: 3},
1585*1c12ee1eSDan Willemsen				{E: `syntax error (line 1:7)`},
1586*1c12ee1eSDan Willemsen			},
1587*1c12ee1eSDan Willemsen		},
1588*1c12ee1eSDan Willemsen		{
1589*1c12ee1eSDan Willemsen			in: "x:\n\n[\"������\"x",
1590*1c12ee1eSDan Willemsen			want: []R{
1591*1c12ee1eSDan Willemsen				{K: text.Name},
1592*1c12ee1eSDan Willemsen				{K: text.ListOpen},
1593*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Str{"������"}}, P: 5},
1594*1c12ee1eSDan Willemsen				{E: `syntax error (line 3:7)`},
1595*1c12ee1eSDan Willemsen			},
1596*1c12ee1eSDan Willemsen		},
1597*1c12ee1eSDan Willemsen		{
1598*1c12ee1eSDan Willemsen			// multi-rune emojis; could be column:8
1599*1c12ee1eSDan Willemsen			in: "x:[\"��������\"x",
1600*1c12ee1eSDan Willemsen			want: []R{
1601*1c12ee1eSDan Willemsen				{K: text.Name},
1602*1c12ee1eSDan Willemsen				{K: text.ListOpen},
1603*1c12ee1eSDan Willemsen				{K: text.Scalar, T: ST{ok: Str{"��������"}}, P: 3},
1604*1c12ee1eSDan Willemsen				{E: `syntax error (line 1:10)`},
1605*1c12ee1eSDan Willemsen			},
1606*1c12ee1eSDan Willemsen		},
1607*1c12ee1eSDan Willemsen	}
1608*1c12ee1eSDan Willemsen
1609*1c12ee1eSDan Willemsen	for _, tc := range tests {
1610*1c12ee1eSDan Willemsen		t.Run("", func(t *testing.T) {
1611*1c12ee1eSDan Willemsen			tc := tc
1612*1c12ee1eSDan Willemsen			in := []byte(tc.in)
1613*1c12ee1eSDan Willemsen			dec := text.NewDecoder(in[:len(in):len(in)])
1614*1c12ee1eSDan Willemsen			for i, want := range tc.want {
1615*1c12ee1eSDan Willemsen				peekTok, peekErr := dec.Peek()
1616*1c12ee1eSDan Willemsen				tok, err := dec.Read()
1617*1c12ee1eSDan Willemsen				if err != nil {
1618*1c12ee1eSDan Willemsen					if want.E == "" {
1619*1c12ee1eSDan Willemsen						errorf(t, tc.in, "Read() got unexpected error: %v", err)
1620*1c12ee1eSDan Willemsen					} else if !strings.Contains(err.Error(), want.E) {
1621*1c12ee1eSDan Willemsen						errorf(t, tc.in, "Read() got %q, want %q", err, want.E)
1622*1c12ee1eSDan Willemsen					}
1623*1c12ee1eSDan Willemsen					return
1624*1c12ee1eSDan Willemsen				}
1625*1c12ee1eSDan Willemsen				if want.E != "" {
1626*1c12ee1eSDan Willemsen					errorf(t, tc.in, "Read() got nil error, want %q", want.E)
1627*1c12ee1eSDan Willemsen					return
1628*1c12ee1eSDan Willemsen				}
1629*1c12ee1eSDan Willemsen				gotK := tok.Kind()
1630*1c12ee1eSDan Willemsen				if gotK != want.K {
1631*1c12ee1eSDan Willemsen					errorf(t, tc.in, "Read() got %v, want %v", gotK, want.K)
1632*1c12ee1eSDan Willemsen					return
1633*1c12ee1eSDan Willemsen				}
1634*1c12ee1eSDan Willemsen				checkToken(t, tok, i, want, tc.in)
1635*1c12ee1eSDan Willemsen				if !cmp.Equal(tok, peekTok, cmp.Comparer(text.TokenEquals)) {
1636*1c12ee1eSDan Willemsen					errorf(t, tc.in, "Peek() %+v != Read() token %+v", peekTok, tok)
1637*1c12ee1eSDan Willemsen				}
1638*1c12ee1eSDan Willemsen				if err != peekErr {
1639*1c12ee1eSDan Willemsen					errorf(t, tc.in, "Peek() error %v != Read() error %v", err, peekErr)
1640*1c12ee1eSDan Willemsen				}
1641*1c12ee1eSDan Willemsen			}
1642*1c12ee1eSDan Willemsen		})
1643*1c12ee1eSDan Willemsen	}
1644*1c12ee1eSDan Willemsen}
1645*1c12ee1eSDan Willemsen
1646*1c12ee1eSDan Willemsenfunc checkToken(t *testing.T, tok text.Token, idx int, r R, in string) {
1647*1c12ee1eSDan Willemsen	// Validate Token.Pos() if R.P is set.
1648*1c12ee1eSDan Willemsen	if r.P > 0 {
1649*1c12ee1eSDan Willemsen		got := tok.Pos()
1650*1c12ee1eSDan Willemsen		if got != r.P {
1651*1c12ee1eSDan Willemsen			errorf(t, in, "want#%d: Token.Pos() got %v want %v", idx, got, r.P)
1652*1c12ee1eSDan Willemsen		}
1653*1c12ee1eSDan Willemsen	}
1654*1c12ee1eSDan Willemsen
1655*1c12ee1eSDan Willemsen	// Validate Token.RawString if R.RS is set.
1656*1c12ee1eSDan Willemsen	if len(r.RS) > 0 {
1657*1c12ee1eSDan Willemsen		got := tok.RawString()
1658*1c12ee1eSDan Willemsen		if got != r.RS {
1659*1c12ee1eSDan Willemsen			errorf(t, in, "want#%d: Token.RawString() got %v want %v", idx, got, r.P)
1660*1c12ee1eSDan Willemsen		}
1661*1c12ee1eSDan Willemsen	}
1662*1c12ee1eSDan Willemsen
1663*1c12ee1eSDan Willemsen	// Skip checking for Token details if r.T is not set.
1664*1c12ee1eSDan Willemsen	if r.T == nil {
1665*1c12ee1eSDan Willemsen		return
1666*1c12ee1eSDan Willemsen	}
1667*1c12ee1eSDan Willemsen
1668*1c12ee1eSDan Willemsen	switch tok.Kind() {
1669*1c12ee1eSDan Willemsen	case text.Name:
1670*1c12ee1eSDan Willemsen		want := r.T.(NT)
1671*1c12ee1eSDan Willemsen		kind := tok.NameKind()
1672*1c12ee1eSDan Willemsen		if kind != want.K {
1673*1c12ee1eSDan Willemsen			errorf(t, in, "want#%d: Token.NameKind() got %v want %v", idx, kind, want.K)
1674*1c12ee1eSDan Willemsen			return
1675*1c12ee1eSDan Willemsen		}
1676*1c12ee1eSDan Willemsen		switch kind {
1677*1c12ee1eSDan Willemsen		case text.IdentName:
1678*1c12ee1eSDan Willemsen			got := tok.IdentName()
1679*1c12ee1eSDan Willemsen			if got != want.S {
1680*1c12ee1eSDan Willemsen				errorf(t, in, "want#%d: Token.IdentName() got %v want %v", idx, got, want.S)
1681*1c12ee1eSDan Willemsen			}
1682*1c12ee1eSDan Willemsen		case text.TypeName:
1683*1c12ee1eSDan Willemsen			got := tok.TypeName()
1684*1c12ee1eSDan Willemsen			if got != want.S {
1685*1c12ee1eSDan Willemsen				errorf(t, in, "want#%d: Token.TypeName() got %v want %v", idx, got, want.S)
1686*1c12ee1eSDan Willemsen			}
1687*1c12ee1eSDan Willemsen		case text.FieldNumber:
1688*1c12ee1eSDan Willemsen			got := tok.FieldNumber()
1689*1c12ee1eSDan Willemsen			if got != want.N {
1690*1c12ee1eSDan Willemsen				errorf(t, in, "want#%d: Token.FieldNumber() got %v want %v", idx, got, want.N)
1691*1c12ee1eSDan Willemsen			}
1692*1c12ee1eSDan Willemsen		}
1693*1c12ee1eSDan Willemsen
1694*1c12ee1eSDan Willemsen	case text.Scalar:
1695*1c12ee1eSDan Willemsen		want := r.T.(ST)
1696*1c12ee1eSDan Willemsen		if ok := want.ok; ok != nil {
1697*1c12ee1eSDan Willemsen			if err := ok.checkOk(tok); err != "" {
1698*1c12ee1eSDan Willemsen				errorf(t, in, "want#%d: %s", idx, err)
1699*1c12ee1eSDan Willemsen			}
1700*1c12ee1eSDan Willemsen		}
1701*1c12ee1eSDan Willemsen		if nok := want.nok; nok != nil {
1702*1c12ee1eSDan Willemsen			if err := nok.checkNok(tok); err != "" {
1703*1c12ee1eSDan Willemsen				errorf(t, in, "want#%d: %s", idx, err)
1704*1c12ee1eSDan Willemsen			}
1705*1c12ee1eSDan Willemsen		}
1706*1c12ee1eSDan Willemsen	}
1707*1c12ee1eSDan Willemsen}
1708*1c12ee1eSDan Willemsen
1709*1c12ee1eSDan Willemsenfunc errorf(t *testing.T, in string, fmtStr string, args ...interface{}) {
1710*1c12ee1eSDan Willemsen	t.Helper()
1711*1c12ee1eSDan Willemsen	vargs := []interface{}{in}
1712*1c12ee1eSDan Willemsen	for _, arg := range args {
1713*1c12ee1eSDan Willemsen		vargs = append(vargs, arg)
1714*1c12ee1eSDan Willemsen	}
1715*1c12ee1eSDan Willemsen	t.Errorf("input:\n%s\n~end~\n"+fmtStr, vargs...)
1716*1c12ee1eSDan Willemsen}
1717*1c12ee1eSDan Willemsen
1718*1c12ee1eSDan Willemsenfunc TestUnmarshalString(t *testing.T) {
1719*1c12ee1eSDan Willemsen	tests := []struct {
1720*1c12ee1eSDan Willemsen		in string
1721*1c12ee1eSDan Willemsen		// want is expected string result.
1722*1c12ee1eSDan Willemsen		want string
1723*1c12ee1eSDan Willemsen		// err is expected error substring from calling DecodeString if set.
1724*1c12ee1eSDan Willemsen		err string
1725*1c12ee1eSDan Willemsen	}{
1726*1c12ee1eSDan Willemsen		{
1727*1c12ee1eSDan Willemsen			in: func() string {
1728*1c12ee1eSDan Willemsen				var b []byte
1729*1c12ee1eSDan Willemsen				for i := 0; i < utf8.RuneSelf; i++ {
1730*1c12ee1eSDan Willemsen					switch i {
1731*1c12ee1eSDan Willemsen					case 0, '\\', '\n', '\'': // these must be escaped, so ignore them
1732*1c12ee1eSDan Willemsen					default:
1733*1c12ee1eSDan Willemsen						b = append(b, byte(i))
1734*1c12ee1eSDan Willemsen					}
1735*1c12ee1eSDan Willemsen				}
1736*1c12ee1eSDan Willemsen				return "'" + string(b) + "'"
1737*1c12ee1eSDan Willemsen			}(),
1738*1c12ee1eSDan Willemsen			want: "\x01\x02\x03\x04\x05\x06\a\b\t\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~\u007f",
1739*1c12ee1eSDan Willemsen		},
1740*1c12ee1eSDan Willemsen		{
1741*1c12ee1eSDan Willemsen			in:  "'\xde\xad\xbe\xef'",
1742*1c12ee1eSDan Willemsen			err: `invalid UTF-8 detected`,
1743*1c12ee1eSDan Willemsen		},
1744*1c12ee1eSDan Willemsen		{
1745*1c12ee1eSDan Willemsen			// Valid UTF-8 wire encoding, but sub-optimal encoding.
1746*1c12ee1eSDan Willemsen			in:  "'\xc0\x80'",
1747*1c12ee1eSDan Willemsen			err: "invalid UTF-8 detected",
1748*1c12ee1eSDan Willemsen		},
1749*1c12ee1eSDan Willemsen		{
1750*1c12ee1eSDan Willemsen			// Valid UTF-8 wire encoding, but invalid rune (surrogate pair).
1751*1c12ee1eSDan Willemsen			in:  "'\xed\xa0\x80'",
1752*1c12ee1eSDan Willemsen			err: "invalid UTF-8 detected",
1753*1c12ee1eSDan Willemsen		},
1754*1c12ee1eSDan Willemsen		{
1755*1c12ee1eSDan Willemsen			// Valid UTF-8 wire encoding, but invalid rune (above max rune).
1756*1c12ee1eSDan Willemsen			in:  "'\xf7\xbf\xbf\xbf'",
1757*1c12ee1eSDan Willemsen			err: "invalid UTF-8 detected",
1758*1c12ee1eSDan Willemsen		},
1759*1c12ee1eSDan Willemsen		{
1760*1c12ee1eSDan Willemsen			// Valid UTF-8 wire encoding of the RuneError rune.
1761*1c12ee1eSDan Willemsen			in:   "'\xef\xbf\xbd'",
1762*1c12ee1eSDan Willemsen			want: string(utf8.RuneError),
1763*1c12ee1eSDan Willemsen		},
1764*1c12ee1eSDan Willemsen		{
1765*1c12ee1eSDan Willemsen			in:   "'hello\u1234world'",
1766*1c12ee1eSDan Willemsen			want: "hello\u1234world",
1767*1c12ee1eSDan Willemsen		},
1768*1c12ee1eSDan Willemsen		{
1769*1c12ee1eSDan Willemsen			in:   `'\"\'\\\?\a\b\n\r\t\v\f\1\12\123\xA\xaB\x12\uAb8f\U0010FFFF'`,
1770*1c12ee1eSDan Willemsen			want: "\"'\\?\a\b\n\r\t\v\f\x01\nS\n\xab\x12\uab8f\U0010ffff",
1771*1c12ee1eSDan Willemsen		},
1772*1c12ee1eSDan Willemsen		{
1773*1c12ee1eSDan Willemsen			in:  `str: '\8'`,
1774*1c12ee1eSDan Willemsen			err: `invalid escape code "\\8" in string`,
1775*1c12ee1eSDan Willemsen		},
1776*1c12ee1eSDan Willemsen		{
1777*1c12ee1eSDan Willemsen			in:   `'\1x'`,
1778*1c12ee1eSDan Willemsen			want: "\001x",
1779*1c12ee1eSDan Willemsen		},
1780*1c12ee1eSDan Willemsen		{
1781*1c12ee1eSDan Willemsen			in:   `'\12x'`,
1782*1c12ee1eSDan Willemsen			want: "\012x",
1783*1c12ee1eSDan Willemsen		},
1784*1c12ee1eSDan Willemsen		{
1785*1c12ee1eSDan Willemsen			in:   `'\123x'`,
1786*1c12ee1eSDan Willemsen			want: "\123x",
1787*1c12ee1eSDan Willemsen		},
1788*1c12ee1eSDan Willemsen		{
1789*1c12ee1eSDan Willemsen			in:   `'\1234x'`,
1790*1c12ee1eSDan Willemsen			want: "\1234x",
1791*1c12ee1eSDan Willemsen		},
1792*1c12ee1eSDan Willemsen		{
1793*1c12ee1eSDan Willemsen			in:   `'\1'`,
1794*1c12ee1eSDan Willemsen			want: "\001",
1795*1c12ee1eSDan Willemsen		},
1796*1c12ee1eSDan Willemsen		{
1797*1c12ee1eSDan Willemsen			in:   `'\12'`,
1798*1c12ee1eSDan Willemsen			want: "\012",
1799*1c12ee1eSDan Willemsen		},
1800*1c12ee1eSDan Willemsen		{
1801*1c12ee1eSDan Willemsen			in:   `'\123'`,
1802*1c12ee1eSDan Willemsen			want: "\123",
1803*1c12ee1eSDan Willemsen		},
1804*1c12ee1eSDan Willemsen		{
1805*1c12ee1eSDan Willemsen			in:   `'\1234'`,
1806*1c12ee1eSDan Willemsen			want: "\1234",
1807*1c12ee1eSDan Willemsen		},
1808*1c12ee1eSDan Willemsen		{
1809*1c12ee1eSDan Willemsen			in:   `'\377'`,
1810*1c12ee1eSDan Willemsen			want: "\377",
1811*1c12ee1eSDan Willemsen		},
1812*1c12ee1eSDan Willemsen		{
1813*1c12ee1eSDan Willemsen			// Overflow octal escape.
1814*1c12ee1eSDan Willemsen			in:  `'\400'`,
1815*1c12ee1eSDan Willemsen			err: `invalid octal escape code "\\400" in string`,
1816*1c12ee1eSDan Willemsen		},
1817*1c12ee1eSDan Willemsen		{
1818*1c12ee1eSDan Willemsen			in:   `'\xfx'`,
1819*1c12ee1eSDan Willemsen			want: "\x0fx",
1820*1c12ee1eSDan Willemsen		},
1821*1c12ee1eSDan Willemsen		{
1822*1c12ee1eSDan Willemsen			in:   `'\xffx'`,
1823*1c12ee1eSDan Willemsen			want: "\xffx",
1824*1c12ee1eSDan Willemsen		},
1825*1c12ee1eSDan Willemsen		{
1826*1c12ee1eSDan Willemsen			in:   `'\xfffx'`,
1827*1c12ee1eSDan Willemsen			want: "\xfffx",
1828*1c12ee1eSDan Willemsen		},
1829*1c12ee1eSDan Willemsen		{
1830*1c12ee1eSDan Willemsen			in:   `'\xf'`,
1831*1c12ee1eSDan Willemsen			want: "\x0f",
1832*1c12ee1eSDan Willemsen		},
1833*1c12ee1eSDan Willemsen		{
1834*1c12ee1eSDan Willemsen			in:   `'\xff'`,
1835*1c12ee1eSDan Willemsen			want: "\xff",
1836*1c12ee1eSDan Willemsen		},
1837*1c12ee1eSDan Willemsen		{
1838*1c12ee1eSDan Willemsen			in:   `'\xfff'`,
1839*1c12ee1eSDan Willemsen			want: "\xfff",
1840*1c12ee1eSDan Willemsen		},
1841*1c12ee1eSDan Willemsen		{
1842*1c12ee1eSDan Willemsen			in:  `'\xz'`,
1843*1c12ee1eSDan Willemsen			err: `invalid hex escape code "\\x" in string`,
1844*1c12ee1eSDan Willemsen		},
1845*1c12ee1eSDan Willemsen		{
1846*1c12ee1eSDan Willemsen			in:  `'\uPo'`,
1847*1c12ee1eSDan Willemsen			err: eofErr,
1848*1c12ee1eSDan Willemsen		},
1849*1c12ee1eSDan Willemsen		{
1850*1c12ee1eSDan Willemsen			in:  `'\uPoo'`,
1851*1c12ee1eSDan Willemsen			err: `invalid Unicode escape code "\\uPoo'" in string`,
1852*1c12ee1eSDan Willemsen		},
1853*1c12ee1eSDan Willemsen		{
1854*1c12ee1eSDan Willemsen			in:  `str: '\uPoop'`,
1855*1c12ee1eSDan Willemsen			err: `invalid Unicode escape code "\\uPoop" in string`,
1856*1c12ee1eSDan Willemsen		},
1857*1c12ee1eSDan Willemsen		{
1858*1c12ee1eSDan Willemsen			// Unmatched surrogate pair.
1859*1c12ee1eSDan Willemsen			in:  `str: '\uDEAD'`,
1860*1c12ee1eSDan Willemsen			err: `unexpected EOF`, // trying to reader other half
1861*1c12ee1eSDan Willemsen		},
1862*1c12ee1eSDan Willemsen		{
1863*1c12ee1eSDan Willemsen			// Surrogate pair with invalid other half.
1864*1c12ee1eSDan Willemsen			in:  `str: '\uDEAD\u0000'`,
1865*1c12ee1eSDan Willemsen			err: `invalid Unicode escape code "\\u0000" in string`,
1866*1c12ee1eSDan Willemsen		},
1867*1c12ee1eSDan Willemsen		{
1868*1c12ee1eSDan Willemsen			// Properly matched surrogate pair.
1869*1c12ee1eSDan Willemsen			in:   `'\uD800\uDEAD'`,
1870*1c12ee1eSDan Willemsen			want: "��",
1871*1c12ee1eSDan Willemsen		},
1872*1c12ee1eSDan Willemsen		{
1873*1c12ee1eSDan Willemsen			// Overflow on Unicode rune.
1874*1c12ee1eSDan Willemsen			in:  `'\U00110000'`,
1875*1c12ee1eSDan Willemsen			err: `invalid Unicode escape code "\\U00110000" in string`,
1876*1c12ee1eSDan Willemsen		},
1877*1c12ee1eSDan Willemsen		{
1878*1c12ee1eSDan Willemsen			in:  `'\z'`,
1879*1c12ee1eSDan Willemsen			err: `invalid escape code "\\z" in string`,
1880*1c12ee1eSDan Willemsen		},
1881*1c12ee1eSDan Willemsen		{
1882*1c12ee1eSDan Willemsen			// Strings cannot have NUL literal since C-style strings forbid them.
1883*1c12ee1eSDan Willemsen			in:  "'\x00'",
1884*1c12ee1eSDan Willemsen			err: `invalid character '\x00' in string`,
1885*1c12ee1eSDan Willemsen		},
1886*1c12ee1eSDan Willemsen		{
1887*1c12ee1eSDan Willemsen			// Strings cannot have newline literal. The C++ permits them if an
1888*1c12ee1eSDan Willemsen			// option is specified to allow them. In Go, we always forbid them.
1889*1c12ee1eSDan Willemsen			in:  "'\n'",
1890*1c12ee1eSDan Willemsen			err: `invalid character '\n' in string`,
1891*1c12ee1eSDan Willemsen		},
1892*1c12ee1eSDan Willemsen	}
1893*1c12ee1eSDan Willemsen
1894*1c12ee1eSDan Willemsen	for _, tc := range tests {
1895*1c12ee1eSDan Willemsen		t.Run("", func(t *testing.T) {
1896*1c12ee1eSDan Willemsen			got, err := text.UnmarshalString(tc.in)
1897*1c12ee1eSDan Willemsen			if err != nil {
1898*1c12ee1eSDan Willemsen				if tc.err == "" {
1899*1c12ee1eSDan Willemsen					errorf(t, tc.in, "UnmarshalString() got unexpected error: %q", err)
1900*1c12ee1eSDan Willemsen				} else if !strings.Contains(err.Error(), tc.err) {
1901*1c12ee1eSDan Willemsen					errorf(t, tc.in, "UnmarshalString() error got %q, want %q", err, tc.err)
1902*1c12ee1eSDan Willemsen				}
1903*1c12ee1eSDan Willemsen				return
1904*1c12ee1eSDan Willemsen			}
1905*1c12ee1eSDan Willemsen			if tc.err != "" {
1906*1c12ee1eSDan Willemsen				errorf(t, tc.in, "UnmarshalString() got nil error, want %q", tc.err)
1907*1c12ee1eSDan Willemsen				return
1908*1c12ee1eSDan Willemsen			}
1909*1c12ee1eSDan Willemsen			if got != tc.want {
1910*1c12ee1eSDan Willemsen				errorf(t, tc.in, "UnmarshalString()\n[got]\n%s\n[want]\n%s", got, tc.want)
1911*1c12ee1eSDan Willemsen			}
1912*1c12ee1eSDan Willemsen		})
1913*1c12ee1eSDan Willemsen	}
1914*1c12ee1eSDan Willemsen}
1915*1c12ee1eSDan Willemsen
1916*1c12ee1eSDan Willemsen// Tests line and column number produced by Decoder.Position.
1917*1c12ee1eSDan Willemsenfunc TestPosition(t *testing.T) {
1918*1c12ee1eSDan Willemsen	dec := text.NewDecoder([]byte("0123456789\n12345\n789"))
1919*1c12ee1eSDan Willemsen
1920*1c12ee1eSDan Willemsen	tests := []struct {
1921*1c12ee1eSDan Willemsen		pos int
1922*1c12ee1eSDan Willemsen		row int
1923*1c12ee1eSDan Willemsen		col int
1924*1c12ee1eSDan Willemsen	}{
1925*1c12ee1eSDan Willemsen		{
1926*1c12ee1eSDan Willemsen			pos: 0,
1927*1c12ee1eSDan Willemsen			row: 1,
1928*1c12ee1eSDan Willemsen			col: 1,
1929*1c12ee1eSDan Willemsen		},
1930*1c12ee1eSDan Willemsen		{
1931*1c12ee1eSDan Willemsen			pos: 10,
1932*1c12ee1eSDan Willemsen			row: 1,
1933*1c12ee1eSDan Willemsen			col: 11,
1934*1c12ee1eSDan Willemsen		},
1935*1c12ee1eSDan Willemsen		{
1936*1c12ee1eSDan Willemsen			pos: 11,
1937*1c12ee1eSDan Willemsen			row: 2,
1938*1c12ee1eSDan Willemsen			col: 1,
1939*1c12ee1eSDan Willemsen		},
1940*1c12ee1eSDan Willemsen		{
1941*1c12ee1eSDan Willemsen			pos: 18,
1942*1c12ee1eSDan Willemsen			row: 3,
1943*1c12ee1eSDan Willemsen			col: 2,
1944*1c12ee1eSDan Willemsen		},
1945*1c12ee1eSDan Willemsen	}
1946*1c12ee1eSDan Willemsen
1947*1c12ee1eSDan Willemsen	for _, tc := range tests {
1948*1c12ee1eSDan Willemsen		t.Run("", func(t *testing.T) {
1949*1c12ee1eSDan Willemsen			row, col := dec.Position(tc.pos)
1950*1c12ee1eSDan Willemsen			if row != tc.row || col != tc.col {
1951*1c12ee1eSDan Willemsen				t.Errorf("Position(%d) got (%d,%d) want (%d,%d)", tc.pos, row, col, tc.row, tc.col)
1952*1c12ee1eSDan Willemsen			}
1953*1c12ee1eSDan Willemsen		})
1954*1c12ee1eSDan Willemsen	}
1955*1c12ee1eSDan Willemsen}
1956