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