From 5df33304e9183a33bc739cbb04e38854148eb004 Mon Sep 17 00:00:00 2001 From: Joe Tsai Date: Thu, 11 Apr 2024 21:46:09 -0700 Subject: [PATCH] Use constructors for static tokens WARNING: This commit includes breaking changes. Instead of global variables, use function constructors for static tokens such as Null, ObjectStart, ObjectEnd, ArrayStart, and ArrayEnd. This provides a greater degree of immutability for the API. Note that static tokens for True and False are dropped in favor of the pre-existing Bool constructor. If necessary, we can already re-introduce True and False. --- arshal.go | 2 +- arshal_any.go | 14 ++-- arshal_default.go | 26 +++---- arshal_test.go | 10 +-- example_orderedobject_test.go | 4 +- jsontext/coder_test.go | 138 +++++++++++++++++----------------- jsontext/decode.go | 14 ++-- jsontext/decode_test.go | 96 +++++++++++------------ jsontext/encode_test.go | 46 ++++++------ jsontext/token.go | 65 ++++++++++------ jsontext/token_test.go | 26 +++---- 11 files changed, 227 insertions(+), 214 deletions(-) diff --git a/arshal.go b/arshal.go index 1b1dc81..11e3c9b 100644 --- a/arshal.go +++ b/arshal.go @@ -198,7 +198,7 @@ func MarshalEncode(out *jsontext.Encoder, in any, opts ...Options) (err error) { func marshalEncode(out *jsontext.Encoder, in any, mo *jsonopts.Struct) (err error) { v := reflect.ValueOf(in) if !v.IsValid() || (v.Kind() == reflect.Pointer && v.IsNil()) { - return out.WriteToken(jsontext.Null) + return out.WriteToken(jsontext.Null()) } // Shallow copy non-pointer values to obtain an addressable value. // It is beneficial to performance to always pass pointers to avoid this. diff --git a/arshal_any.go b/arshal_any.go index 317d572..e6d7819 100644 --- a/arshal_any.go +++ b/arshal_any.go @@ -22,7 +22,7 @@ import ( func marshalValueAny(enc *jsontext.Encoder, val any, mo *jsonopts.Struct) error { switch val := val.(type) { case nil: - return enc.WriteToken(jsontext.Null) + return enc.WriteToken(jsontext.Null()) case bool: return enc.WriteToken(jsontext.Bool(val)) case string: @@ -96,7 +96,7 @@ func marshalObjectAny(enc *jsontext.Encoder, obj map[string]any, mo *jsonopts.St // Handle empty maps. if len(obj) == 0 { if mo.Flags.Get(jsonflags.FormatNilMapAsNull) && obj == nil { - return enc.WriteToken(jsontext.Null) + return enc.WriteToken(jsontext.Null()) } // Optimize for marshaling an empty map without any preceding whitespace. if !xe.Flags.Get(jsonflags.AnyWhitespace) && !xe.Tokens.Last.NeedObjectName() { @@ -109,7 +109,7 @@ func marshalObjectAny(enc *jsontext.Encoder, obj map[string]any, mo *jsonopts.St } } - if err := enc.WriteToken(jsontext.ObjectStart); err != nil { + if err := enc.WriteToken(jsontext.ObjectStart()); err != nil { return err } // A Go map guarantees that each entry has a unique key @@ -144,7 +144,7 @@ func marshalObjectAny(enc *jsontext.Encoder, obj map[string]any, mo *jsonopts.St } putStrings(names) } - if err := enc.WriteToken(jsontext.ObjectEnd); err != nil { + if err := enc.WriteToken(jsontext.ObjectEnd()); err != nil { return err } return nil @@ -209,7 +209,7 @@ func marshalArrayAny(enc *jsontext.Encoder, arr []any, mo *jsonopts.Struct) erro // Handle empty slices. if len(arr) == 0 { if mo.Flags.Get(jsonflags.FormatNilSliceAsNull) && arr == nil { - return enc.WriteToken(jsontext.Null) + return enc.WriteToken(jsontext.Null()) } // Optimize for marshaling an empty slice without any preceding whitespace. if !xe.Flags.Get(jsonflags.AnyWhitespace) && !xe.Tokens.Last.NeedObjectName() { @@ -222,7 +222,7 @@ func marshalArrayAny(enc *jsontext.Encoder, arr []any, mo *jsonopts.Struct) erro } } - if err := enc.WriteToken(jsontext.ArrayStart); err != nil { + if err := enc.WriteToken(jsontext.ArrayStart()); err != nil { return err } for _, val := range arr { @@ -230,7 +230,7 @@ func marshalArrayAny(enc *jsontext.Encoder, arr []any, mo *jsonopts.Struct) erro return err } } - if err := enc.WriteToken(jsontext.ArrayEnd); err != nil { + if err := enc.WriteToken(jsontext.ArrayEnd()); err != nil { return err } return nil diff --git a/arshal_default.go b/arshal_default.go index 4bbcd05..7cffaa9 100644 --- a/arshal_default.go +++ b/arshal_default.go @@ -267,7 +267,7 @@ func makeBytesArshaler(t reflect.Type, fncs *arshaler) *arshaler { } if mo.Flags.Get(jsonflags.FormatNilSliceAsNull) && va.Kind() == reflect.Slice && va.IsNil() { // TODO: Provide a "emitempty" format override? - return enc.WriteToken(jsontext.Null) + return enc.WriteToken(jsontext.Null()) } val := enc.UnusedBuffer() b := va.Bytes() @@ -648,7 +648,7 @@ func makeMapArshaler(t reflect.Type) *arshaler { n := va.Len() if n == 0 { if emitNull && va.IsNil() { - return enc.WriteToken(jsontext.Null) + return enc.WriteToken(jsontext.Null()) } // Optimize for marshaling an empty map without any preceding whitespace. if optimizeCommon && !xe.Flags.Get(jsonflags.AnyWhitespace) && !xe.Tokens.Last.NeedObjectName() { @@ -662,7 +662,7 @@ func makeMapArshaler(t reflect.Type) *arshaler { } once.Do(init) - if err := enc.WriteToken(jsontext.ObjectStart); err != nil { + if err := enc.WriteToken(jsontext.ObjectStart()); err != nil { return err } if n > 0 { @@ -767,7 +767,7 @@ func makeMapArshaler(t reflect.Type) *arshaler { } } } - if err := enc.WriteToken(jsontext.ObjectEnd); err != nil { + if err := enc.WriteToken(jsontext.ObjectEnd()); err != nil { return err } return nil @@ -918,7 +918,7 @@ func makeStructArshaler(t reflect.Type) *arshaler { err.action = "marshal" return &err } - if err := enc.WriteToken(jsontext.ObjectStart); err != nil { + if err := enc.WriteToken(jsontext.ObjectStart()); err != nil { return err } var seenIdxs uintSet @@ -1064,7 +1064,7 @@ func makeStructArshaler(t reflect.Type) *arshaler { return err } } - if err := enc.WriteToken(jsontext.ObjectEnd); err != nil { + if err := enc.WriteToken(jsontext.ObjectEnd()); err != nil { return err } return nil @@ -1253,7 +1253,7 @@ func makeSliceArshaler(t reflect.Type) *arshaler { n := va.Len() if n == 0 { if emitNull && va.IsNil() { - return enc.WriteToken(jsontext.Null) + return enc.WriteToken(jsontext.Null()) } // Optimize for marshaling an empty slice without any preceding whitespace. if optimizeCommon && !xe.Flags.Get(jsonflags.AnyWhitespace) && !xe.Tokens.Last.NeedObjectName() { @@ -1267,7 +1267,7 @@ func makeSliceArshaler(t reflect.Type) *arshaler { } once.Do(init) - if err := enc.WriteToken(jsontext.ArrayStart); err != nil { + if err := enc.WriteToken(jsontext.ArrayStart()); err != nil { return err } marshal := valFncs.marshal @@ -1280,7 +1280,7 @@ func makeSliceArshaler(t reflect.Type) *arshaler { return err } } - if err := enc.WriteToken(jsontext.ArrayEnd); err != nil { + if err := enc.WriteToken(jsontext.ArrayEnd()); err != nil { return err } return nil @@ -1366,7 +1366,7 @@ func makeArrayArshaler(t reflect.Type) *arshaler { return newInvalidFormatError("marshal", t, mo.Format) } once.Do(init) - if err := enc.WriteToken(jsontext.ArrayStart); err != nil { + if err := enc.WriteToken(jsontext.ArrayStart()); err != nil { return err } marshal := valFncs.marshal @@ -1379,7 +1379,7 @@ func makeArrayArshaler(t reflect.Type) *arshaler { return err } } - if err := enc.WriteToken(jsontext.ArrayEnd); err != nil { + if err := enc.WriteToken(jsontext.ArrayEnd()); err != nil { return err } return nil @@ -1464,7 +1464,7 @@ func makePointerArshaler(t reflect.Type) *arshaler { // NOTE: Struct.Format is forwarded to underlying marshal. if va.IsNil() { - return enc.WriteToken(jsontext.Null) + return enc.WriteToken(jsontext.Null()) } once.Do(init) marshal := valFncs.marshal @@ -1509,7 +1509,7 @@ func makeInterfaceArshaler(t reflect.Type) *arshaler { return newInvalidFormatError("marshal", t, mo.Format) } if va.IsNil() { - return enc.WriteToken(jsontext.Null) + return enc.WriteToken(jsontext.Null()) } v := newAddressableValue(va.Elem().Type()) v.Set(va.Elem()) diff --git a/arshal_test.go b/arshal_test.go index f189e61..88f8d43 100644 --- a/arshal_test.go +++ b/arshal_test.go @@ -3118,8 +3118,8 @@ func TestMarshal(t *testing.T) { }, { name: jsontest.Name("Methods/Invalid/JSONv2/TooMany"), in: marshalJSONv2Func(func(enc *jsontext.Encoder, opts Options) error { - enc.WriteToken(jsontext.Null) - enc.WriteToken(jsontext.Null) + enc.WriteToken(jsontext.Null()) + enc.WriteToken(jsontext.Null()) return nil }), want: `nullnull`, @@ -3198,7 +3198,7 @@ func TestMarshal(t *testing.T) { name: jsontest.Name("Methods/Invalid/MapKey/JSONv2/Syntax"), in: map[any]string{ addr(marshalJSONv2Func(func(enc *jsontext.Encoder, opts Options) error { - return enc.WriteToken(jsontext.Null) + return enc.WriteToken(jsontext.Null()) })): "invalid", }, want: `{`, @@ -3483,7 +3483,7 @@ func TestMarshal(t *testing.T) { name: jsontest.Name("Functions/Map/Key/NoCaseString/V2/InvalidToken"), opts: []Options{ WithMarshalers(MarshalFuncV2(func(enc *jsontext.Encoder, v nocaseString, opts Options) error { - return enc.WriteToken(jsontext.Null) + return enc.WriteToken(jsontext.Null()) })), }, in: map[nocaseString]string{"hello": "world"}, @@ -8469,7 +8469,7 @@ func TestMarshalInvalidNamespace(t *testing.T) { t.Fatalf("%s: MarshalEncode error is nil, want non-nil", tt.name.Where) } for _, tok := range []jsontext.Token{ - jsontext.Null, jsontext.String(""), jsontext.Int(0), jsontext.ObjectStart, jsontext.ObjectEnd, jsontext.ArrayStart, jsontext.ArrayEnd, + jsontext.Null(), jsontext.String(""), jsontext.Int(0), jsontext.ObjectStart(), jsontext.ObjectEnd(), jsontext.ArrayStart(), jsontext.ArrayEnd(), } { if err := enc.WriteToken(tok); err == nil { t.Fatalf("%s: WriteToken error is nil, want non-nil", tt.name.Where) diff --git a/example_orderedobject_test.go b/example_orderedobject_test.go index 5a1e813..bda2929 100644 --- a/example_orderedobject_test.go +++ b/example_orderedobject_test.go @@ -30,7 +30,7 @@ type ObjectMember[V any] struct { // MarshalJSONV2 encodes obj as a JSON object into enc. func (obj *OrderedObject[V]) MarshalJSONV2(enc *jsontext.Encoder, opts json.Options) error { - if err := enc.WriteToken(jsontext.ObjectStart); err != nil { + if err := enc.WriteToken(jsontext.ObjectStart()); err != nil { return err } for i := range *obj { @@ -42,7 +42,7 @@ func (obj *OrderedObject[V]) MarshalJSONV2(enc *jsontext.Encoder, opts json.Opti return err } } - if err := enc.WriteToken(jsontext.ObjectEnd); err != nil { + if err := enc.WriteToken(jsontext.ObjectEnd()); err != nil { return err } return nil diff --git a/jsontext/coder_test.go b/jsontext/coder_test.go index 65f2ff9..205408c 100644 --- a/jsontext/coder_test.go +++ b/jsontext/coder_test.go @@ -45,18 +45,18 @@ var coderTestdata = []coderTestdataEntry{{ name: jsontest.Name("Null"), in: ` null `, outCompacted: `null`, - tokens: []Token{Null}, + tokens: []Token{Null()}, pointers: []string{""}, }, { name: jsontest.Name("False"), in: ` false `, outCompacted: `false`, - tokens: []Token{False}, + tokens: []Token{Bool(false)}, }, { name: jsontest.Name("True"), in: ` true `, outCompacted: `true`, - tokens: []Token{True}, + tokens: []Token{Bool(true)}, }, { name: jsontest.Name("EmptyString"), in: ` "" `, @@ -150,12 +150,12 @@ var coderTestdata = []coderTestdataEntry{{ ]`, outCanonicalized: `[0,0,0,0,1,1.7976931348623157e+308,-5e-324,1e+100,1.7976931348623157e+308,9007199254740990,9007199254740991,9007199254740992,9007199254740992,9007199254740994,-9223372036854776000,9223372036854776000,0,18446744073709552000]`, tokens: []Token{ - ArrayStart, + ArrayStart(), Float(0), Float(math.Copysign(0, -1)), rawToken(`0.0`), rawToken(`-0.0`), rawToken(`1.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001`), rawToken(`1e1000`), Float(-5e-324), Float(1e100), Float(1.7976931348623157e+308), Float(9007199254740990), Float(9007199254740991), Float(9007199254740992), rawToken(`9007199254740993`), rawToken(`9007199254740994`), Int(minInt64), Int(maxInt64), Uint(minUint64), Uint(maxUint64), - ArrayEnd, + ArrayEnd(), }, pointers: []string{ "", "/0", "/1", "/2", "/3", "/4", "/5", "/6", "/7", "/8", "/9", "/10", "/11", "/12", "/13", "/14", "/15", "/16", "/17", "", @@ -164,7 +164,7 @@ var coderTestdata = []coderTestdataEntry{{ name: jsontest.Name("ObjectN0"), in: ` { } `, outCompacted: `{}`, - tokens: []Token{ObjectStart, ObjectEnd}, + tokens: []Token{ObjectStart(), ObjectEnd()}, pointers: []string{"", ""}, }, { name: jsontest.Name("ObjectN1"), @@ -174,7 +174,7 @@ var coderTestdata = []coderTestdataEntry{{ outIndented: `{ "0": 0 }`, - tokens: []Token{ObjectStart, String("0"), Uint(0), ObjectEnd}, + tokens: []Token{ObjectStart(), String("0"), Uint(0), ObjectEnd()}, pointers: []string{"", "/0", "/0", ""}, }, { name: jsontest.Name("ObjectN2"), @@ -185,7 +185,7 @@ var coderTestdata = []coderTestdataEntry{{ "0": 0, "1": 1 }`, - tokens: []Token{ObjectStart, String("0"), Uint(0), String("1"), Uint(1), ObjectEnd}, + tokens: []Token{ObjectStart(), String("0"), Uint(0), String("1"), Uint(1), ObjectEnd()}, pointers: []string{"", "/0", "/0", "/1", "/1", ""}, }, { name: jsontest.Name("ObjectNested"), @@ -203,7 +203,7 @@ var coderTestdata = []coderTestdataEntry{{ } } }`, - tokens: []Token{ObjectStart, String("0"), ObjectStart, String("1"), ObjectStart, String("2"), ObjectStart, String("3"), ObjectStart, String("4"), ObjectStart, ObjectEnd, ObjectEnd, ObjectEnd, ObjectEnd, ObjectEnd, ObjectEnd}, + tokens: []Token{ObjectStart(), String("0"), ObjectStart(), String("1"), ObjectStart(), String("2"), ObjectStart(), String("3"), ObjectStart(), String("4"), ObjectStart(), ObjectEnd(), ObjectEnd(), ObjectEnd(), ObjectEnd(), ObjectEnd(), ObjectEnd()}, pointers: []string{ "", "/0", "/0", @@ -250,23 +250,23 @@ var coderTestdata = []coderTestdataEntry{{ }`, outCanonicalized: `{"":{"0":{"11":"","222":"aaaaa","3333":"bbb"},"44444":{"555555":"aaaa","6666666":"ccccccc","77777777":"bb"}}}`, tokens: []Token{ - ObjectStart, + ObjectStart(), String(""), - ObjectStart, + ObjectStart(), String("44444"), - ObjectStart, + ObjectStart(), String("6666666"), String("ccccccc"), String("77777777"), String("bb"), String("555555"), String("aaaa"), - ObjectEnd, + ObjectEnd(), String("0"), - ObjectStart, + ObjectStart(), String("3333"), String("bbb"), String("11"), String(""), String("222"), String("aaaaa"), - ObjectEnd, - ObjectEnd, - ObjectEnd, + ObjectEnd(), + ObjectEnd(), + ObjectEnd(), }, pointers: []string{ "", @@ -288,7 +288,7 @@ var coderTestdata = []coderTestdataEntry{{ name: jsontest.Name("ArrayN0"), in: ` [ ] `, outCompacted: `[]`, - tokens: []Token{ArrayStart, ArrayEnd}, + tokens: []Token{ArrayStart(), ArrayEnd()}, pointers: []string{"", ""}, }, { name: jsontest.Name("ArrayN1"), @@ -297,7 +297,7 @@ var coderTestdata = []coderTestdataEntry{{ outIndented: `[ 0 ]`, - tokens: []Token{ArrayStart, Uint(0), ArrayEnd}, + tokens: []Token{ArrayStart(), Uint(0), ArrayEnd()}, pointers: []string{"", "/0", ""}, }, { name: jsontest.Name("ArrayN2"), @@ -307,7 +307,7 @@ var coderTestdata = []coderTestdataEntry{{ 0, 1 ]`, - tokens: []Token{ArrayStart, Uint(0), Uint(1), ArrayEnd}, + tokens: []Token{ArrayStart(), Uint(0), Uint(1), ArrayEnd()}, }, { name: jsontest.Name("ArrayNested"), in: ` [ [ [ [ [ ] ] ] ] ] `, @@ -321,7 +321,7 @@ var coderTestdata = []coderTestdataEntry{{ ] ] ]`, - tokens: []Token{ArrayStart, ArrayStart, ArrayStart, ArrayStart, ArrayStart, ArrayEnd, ArrayEnd, ArrayEnd, ArrayEnd, ArrayEnd}, + tokens: []Token{ArrayStart(), ArrayStart(), ArrayStart(), ArrayStart(), ArrayStart(), ArrayEnd(), ArrayEnd(), ArrayEnd(), ArrayEnd(), ArrayEnd()}, pointers: []string{ "", "/0", @@ -376,17 +376,17 @@ var coderTestdata = []coderTestdataEntry{{ }`, outCanonicalized: `{"arrayN0":[],"arrayN1":[0],"arrayN2":[0,1],"literals":[null,false,true],"number":3.14159,"objectN0":{},"objectN1":{"0":0},"objectN2":{"0":0,"1":1},"string":"Hello, 世界"}`, tokens: []Token{ - ObjectStart, - String("literals"), ArrayStart, Null, False, True, ArrayEnd, + ObjectStart(), + String("literals"), ArrayStart(), Null(), Bool(false), Bool(true), ArrayEnd(), String("string"), String("Hello, 世界"), String("number"), Float(3.14159), - String("arrayN0"), ArrayStart, ArrayEnd, - String("arrayN1"), ArrayStart, Uint(0), ArrayEnd, - String("arrayN2"), ArrayStart, Uint(0), Uint(1), ArrayEnd, - String("objectN0"), ObjectStart, ObjectEnd, - String("objectN1"), ObjectStart, String("0"), Uint(0), ObjectEnd, - String("objectN2"), ObjectStart, String("0"), Uint(0), String("1"), Uint(1), ObjectEnd, - ObjectEnd, + String("arrayN0"), ArrayStart(), ArrayEnd(), + String("arrayN1"), ArrayStart(), Uint(0), ArrayEnd(), + String("arrayN2"), ArrayStart(), Uint(0), Uint(1), ArrayEnd(), + String("objectN0"), ObjectStart(), ObjectEnd(), + String("objectN1"), ObjectStart(), String("0"), Uint(0), ObjectEnd(), + String("objectN2"), ObjectStart(), String("0"), Uint(0), String("1"), Uint(1), ObjectEnd(), + ObjectEnd(), }, pointers: []string{ "", @@ -497,54 +497,54 @@ func TestCoderStackPointer(t *testing.T) { wantWithRejectDuplicateNames string wantWithAllowDuplicateNames string }{ - {Null, "", ""}, + {Null(), "", ""}, - {ArrayStart, "", ""}, - {ArrayEnd, "", ""}, + {ArrayStart(), "", ""}, + {ArrayEnd(), "", ""}, - {ArrayStart, "", ""}, + {ArrayStart(), "", ""}, {Bool(true), "/0", "/0"}, - {ArrayEnd, "", ""}, + {ArrayEnd(), "", ""}, - {ArrayStart, "", ""}, + {ArrayStart(), "", ""}, {String("hello"), "/0", "/0"}, {String("goodbye"), "/1", "/1"}, - {ArrayEnd, "", ""}, + {ArrayEnd(), "", ""}, - {ObjectStart, "", ""}, - {ObjectEnd, "", ""}, + {ObjectStart(), "", ""}, + {ObjectEnd(), "", ""}, - {ObjectStart, "", ""}, + {ObjectStart(), "", ""}, {String("hello"), "/hello", "/0"}, {String("goodbye"), "/hello", "/0"}, - {ObjectEnd, "", ""}, + {ObjectEnd(), "", ""}, - {ObjectStart, "", ""}, + {ObjectStart(), "", ""}, {String(""), "/", "/0"}, - {Null, "/", "/0"}, + {Null(), "/", "/0"}, {String("0"), "/0", "/1"}, - {Null, "/0", "/1"}, + {Null(), "/0", "/1"}, {String("~"), "/~0", "/2"}, - {Null, "/~0", "/2"}, + {Null(), "/~0", "/2"}, {String("/"), "/~1", "/3"}, - {Null, "/~1", "/3"}, + {Null(), "/~1", "/3"}, {String("a//b~/c/~d~~e"), "/a~1~1b~0~1c~1~0d~0~0e", "/4"}, - {Null, "/a~1~1b~0~1c~1~0d~0~0e", "/4"}, + {Null(), "/a~1~1b~0~1c~1~0d~0~0e", "/4"}, {String(" \r\n\t"), "/ \r\n\t", "/5"}, - {Null, "/ \r\n\t", "/5"}, - {ObjectEnd, "", ""}, + {Null(), "/ \r\n\t", "/5"}, + {ObjectEnd(), "", ""}, - {ArrayStart, "", ""}, - {ObjectStart, "/0", "/0"}, + {ArrayStart(), "", ""}, + {ObjectStart(), "/0", "/0"}, {String(""), "/0/", "/0/0"}, - {ArrayStart, "/0/", "/0/0"}, - {ObjectStart, "/0//0", "/0/0/0"}, + {ArrayStart(), "/0/", "/0/0"}, + {ObjectStart(), "/0//0", "/0/0/0"}, {String("#"), "/0//0/#", "/0/0/0/0"}, - {Null, "/0//0/#", "/0/0/0/0"}, - {ObjectEnd, "/0//0", "/0/0/0"}, - {ArrayEnd, "/0/", "/0/0"}, - {ObjectEnd, "/0", "/0"}, - {ArrayEnd, "", ""}, + {Null(), "/0//0/#", "/0/0/0/0"}, + {ObjectEnd(), "/0//0", "/0/0/0"}, + {ArrayEnd(), "/0/", "/0/0"}, + {ObjectEnd(), "/0", "/0"}, + {ArrayEnd(), "", ""}, } for _, allowDupes := range []bool{false, true} { @@ -708,19 +708,19 @@ func TestCoderMaxDepth(t *testing.T) { }) t.Run("Arrays/TokenThenValue", func(t *testing.T) { enc.s.reset(enc.s.Buf[:0], nil) - checkWriteToken(t, ArrayStart, nil) + checkWriteToken(t, ArrayStart(), nil) checkWriteValue(t, trimArray(maxArrays), errMaxDepth.withOffset(maxNestingDepth)) checkWriteValue(t, trimArray(trimArray(maxArrays)), nil) - checkWriteToken(t, ArrayEnd, nil) + checkWriteToken(t, ArrayEnd(), nil) }) t.Run("Arrays/AllTokens", func(t *testing.T) { enc.s.reset(enc.s.Buf[:0], nil) for i := 0; i < maxNestingDepth; i++ { - checkWriteToken(t, ArrayStart, nil) + checkWriteToken(t, ArrayStart(), nil) } - checkWriteToken(t, ArrayStart, errMaxDepth.withOffset(maxNestingDepth)) + checkWriteToken(t, ArrayStart(), errMaxDepth.withOffset(maxNestingDepth)) for i := 0; i < maxNestingDepth; i++ { - checkWriteToken(t, ArrayEnd, nil) + checkWriteToken(t, ArrayEnd(), nil) } }) @@ -731,24 +731,24 @@ func TestCoderMaxDepth(t *testing.T) { }) t.Run("Objects/TokenThenValue", func(t *testing.T) { enc.s.reset(enc.s.Buf[:0], nil) - checkWriteToken(t, ObjectStart, nil) + checkWriteToken(t, ObjectStart(), nil) checkWriteToken(t, String(""), nil) checkWriteValue(t, trimObject(maxObjects), errMaxDepth.withOffset(maxNestingDepth*len64(`{"":`))) checkWriteValue(t, trimObject(trimObject(maxObjects)), nil) - checkWriteToken(t, ObjectEnd, nil) + checkWriteToken(t, ObjectEnd(), nil) }) t.Run("Objects/AllTokens", func(t *testing.T) { enc.s.reset(enc.s.Buf[:0], nil) for i := 0; i < maxNestingDepth-1; i++ { - checkWriteToken(t, ObjectStart, nil) + checkWriteToken(t, ObjectStart(), nil) checkWriteToken(t, String(""), nil) } - checkWriteToken(t, ObjectStart, nil) + checkWriteToken(t, ObjectStart(), nil) checkWriteToken(t, String(""), nil) - checkWriteToken(t, ObjectStart, errMaxDepth.withOffset(maxNestingDepth*len64(`{"":`))) + checkWriteToken(t, ObjectStart(), errMaxDepth.withOffset(maxNestingDepth*len64(`{"":`))) checkWriteToken(t, String(""), nil) for i := 0; i < maxNestingDepth; i++ { - checkWriteToken(t, ObjectEnd, nil) + checkWriteToken(t, ObjectEnd(), nil) } }) }) diff --git a/jsontext/decode.go b/jsontext/decode.go index db39b8a..32ae2a9 100644 --- a/jsontext/decode.go +++ b/jsontext/decode.go @@ -446,7 +446,7 @@ func (d *decoderState) ReadToken() (Token, error) { return Token{}, d.injectSyntacticErrorWithPosition(err, pos-len("null")) // report position at start of literal } d.prevStart, d.prevEnd = pos, pos - return Null, nil + return Null(), nil case 'f': if jsonwire.ConsumeFalse(d.buf[pos:]) == 0 { @@ -461,7 +461,7 @@ func (d *decoderState) ReadToken() (Token, error) { return Token{}, d.injectSyntacticErrorWithPosition(err, pos-len("false")) // report position at start of literal } d.prevStart, d.prevEnd = pos, pos - return False, nil + return Bool(false), nil case 't': if jsonwire.ConsumeTrue(d.buf[pos:]) == 0 { @@ -476,7 +476,7 @@ func (d *decoderState) ReadToken() (Token, error) { return Token{}, d.injectSyntacticErrorWithPosition(err, pos-len("true")) // report position at start of literal } d.prevStart, d.prevEnd = pos, pos - return True, nil + return Bool(true), nil case '"': var flags jsonwire.ValueFlags // TODO: Preserve this in Token? @@ -537,7 +537,7 @@ func (d *decoderState) ReadToken() (Token, error) { } pos += 1 d.prevStart, d.prevEnd = pos, pos - return ObjectStart, nil + return objectStartToken, nil case '}': if err = d.Tokens.popObject(); err != nil { @@ -549,7 +549,7 @@ func (d *decoderState) ReadToken() (Token, error) { } pos += 1 d.prevStart, d.prevEnd = pos, pos - return ObjectEnd, nil + return objectEndToken, nil case '[': if err = d.Tokens.pushArray(); err != nil { @@ -557,7 +557,7 @@ func (d *decoderState) ReadToken() (Token, error) { } pos += 1 d.prevStart, d.prevEnd = pos, pos - return ArrayStart, nil + return arrayStartToken, nil case ']': if err = d.Tokens.popArray(); err != nil { @@ -565,7 +565,7 @@ func (d *decoderState) ReadToken() (Token, error) { } pos += 1 d.prevStart, d.prevEnd = pos, pos - return ArrayEnd, nil + return arrayEndToken, nil default: err = newInvalidCharacterError(d.buf[pos:], "at start of token") diff --git a/jsontext/decode_test.go b/jsontext/decode_test.go index fc156ed..de05d52 100644 --- a/jsontext/decode_test.go +++ b/jsontext/decode_test.go @@ -203,7 +203,7 @@ var decoderErrorTestdata = []struct { name: jsontest.Name("StreamN1"), in: ` null `, calls: []decoderMethodCall{ - {'n', Null, nil, ""}, + {'n', Null(), nil, ""}, {0, zeroToken, io.EOF, ""}, {0, zeroValue, io.EOF, ""}, }, @@ -212,8 +212,8 @@ var decoderErrorTestdata = []struct { name: jsontest.Name("StreamN2"), in: ` nullnull `, calls: []decoderMethodCall{ - {'n', Null, nil, ""}, - {'n', Null, nil, ""}, + {'n', Null(), nil, ""}, + {'n', Null(), nil, ""}, {0, zeroToken, io.EOF, ""}, {0, zeroValue, io.EOF, ""}, }, @@ -222,7 +222,7 @@ var decoderErrorTestdata = []struct { name: jsontest.Name("StreamN2/ExtraComma"), // stream is whitespace delimited, not comma delimited in: ` null , null `, calls: []decoderMethodCall{ - {'n', Null, nil, ""}, + {'n', Null(), nil, ""}, {0, zeroToken, newInvalidCharacterError(",", `before next token`).withOffset(len64(` null `)), ""}, {0, zeroValue, newInvalidCharacterError(",", `before next token`).withOffset(len64(` null `)), ""}, }, @@ -326,7 +326,7 @@ var decoderErrorTestdata = []struct { in: `{`, calls: []decoderMethodCall{ {'{', zeroValue, io.ErrUnexpectedEOF, ""}, - {'{', ObjectStart, nil, ""}, + {'{', ObjectStart(), nil, ""}, {0, zeroToken, io.ErrUnexpectedEOF, ""}, {0, zeroValue, io.ErrUnexpectedEOF, ""}, }, @@ -336,7 +336,7 @@ var decoderErrorTestdata = []struct { in: `{"0"`, calls: []decoderMethodCall{ {'{', zeroValue, io.ErrUnexpectedEOF, ""}, - {'{', ObjectStart, nil, ""}, + {'{', ObjectStart(), nil, ""}, {'"', String("0"), nil, ""}, {0, zeroToken, io.ErrUnexpectedEOF, ""}, {0, zeroValue, io.ErrUnexpectedEOF, ""}, @@ -347,7 +347,7 @@ var decoderErrorTestdata = []struct { in: `{"0":`, calls: []decoderMethodCall{ {'{', zeroValue, io.ErrUnexpectedEOF, ""}, - {'{', ObjectStart, nil, ""}, + {'{', ObjectStart(), nil, ""}, {'"', String("0"), nil, ""}, {0, zeroToken, io.ErrUnexpectedEOF, ""}, {0, zeroValue, io.ErrUnexpectedEOF, ""}, @@ -358,7 +358,7 @@ var decoderErrorTestdata = []struct { in: `{"0":0`, calls: []decoderMethodCall{ {'{', zeroValue, io.ErrUnexpectedEOF, ""}, - {'{', ObjectStart, nil, ""}, + {'{', ObjectStart(), nil, ""}, {'"', String("0"), nil, ""}, {'0', Uint(0), nil, ""}, {0, zeroToken, io.ErrUnexpectedEOF, ""}, @@ -370,7 +370,7 @@ var decoderErrorTestdata = []struct { in: `{"0":0,`, calls: []decoderMethodCall{ {'{', zeroValue, io.ErrUnexpectedEOF, ""}, - {'{', ObjectStart, nil, ""}, + {'{', ObjectStart(), nil, ""}, {'"', String("0"), nil, ""}, {'0', Uint(0), nil, ""}, {0, zeroToken, io.ErrUnexpectedEOF, ""}, @@ -382,7 +382,7 @@ var decoderErrorTestdata = []struct { in: ` { "fizz" "buzz" } `, calls: []decoderMethodCall{ {'{', zeroValue, newInvalidCharacterError("\"", "after object name (expecting ':')").withOffset(len64(` { "fizz" `)), ""}, - {'{', ObjectStart, nil, ""}, + {'{', ObjectStart(), nil, ""}, {'"', String("fizz"), nil, ""}, {0, zeroToken, errMissingColon.withOffset(len64(` { "fizz" `)), ""}, {0, zeroValue, errMissingColon.withOffset(len64(` { "fizz" `)), ""}, @@ -393,7 +393,7 @@ var decoderErrorTestdata = []struct { in: ` { "fizz" , "buzz" } `, calls: []decoderMethodCall{ {'{', zeroValue, newInvalidCharacterError(",", "after object name (expecting ':')").withOffset(len64(` { "fizz" `)), ""}, - {'{', ObjectStart, nil, ""}, + {'{', ObjectStart(), nil, ""}, {'"', String("fizz"), nil, ""}, {0, zeroToken, errMissingColon.withOffset(len64(` { "fizz" `)), ""}, {0, zeroValue, errMissingColon.withOffset(len64(` { "fizz" `)), ""}, @@ -404,7 +404,7 @@ var decoderErrorTestdata = []struct { in: ` { "fizz" # "buzz" } `, calls: []decoderMethodCall{ {'{', zeroValue, newInvalidCharacterError("#", "after object name (expecting ':')").withOffset(len64(` { "fizz" `)), ""}, - {'{', ObjectStart, nil, ""}, + {'{', ObjectStart(), nil, ""}, {'"', String("fizz"), nil, ""}, {0, zeroToken, errMissingColon.withOffset(len64(` { "fizz" `)), ""}, {0, zeroValue, errMissingColon.withOffset(len64(` { "fizz" `)), ""}, @@ -415,7 +415,7 @@ var decoderErrorTestdata = []struct { in: ` { "fizz" : "buzz" "gazz" } `, calls: []decoderMethodCall{ {'{', zeroValue, newInvalidCharacterError("\"", "after object value (expecting ',' or '}')").withOffset(len64(` { "fizz" : "buzz" `)), ""}, - {'{', ObjectStart, nil, ""}, + {'{', ObjectStart(), nil, ""}, {'"', String("fizz"), nil, ""}, {'"', String("buzz"), nil, ""}, {0, zeroToken, errMissingComma.withOffset(len64(` { "fizz" : "buzz" `)), ""}, @@ -427,7 +427,7 @@ var decoderErrorTestdata = []struct { in: ` { "fizz" : "buzz" : "gazz" } `, calls: []decoderMethodCall{ {'{', zeroValue, newInvalidCharacterError(":", "after object value (expecting ',' or '}')").withOffset(len64(` { "fizz" : "buzz" `)), ""}, - {'{', ObjectStart, nil, ""}, + {'{', ObjectStart(), nil, ""}, {'"', String("fizz"), nil, ""}, {'"', String("buzz"), nil, ""}, {0, zeroToken, errMissingComma.withOffset(len64(` { "fizz" : "buzz" `)), ""}, @@ -439,7 +439,7 @@ var decoderErrorTestdata = []struct { in: ` { "fizz" : "buzz" # "gazz" } `, calls: []decoderMethodCall{ {'{', zeroValue, newInvalidCharacterError("#", "after object value (expecting ',' or '}')").withOffset(len64(` { "fizz" : "buzz" `)), ""}, - {'{', ObjectStart, nil, ""}, + {'{', ObjectStart(), nil, ""}, {'"', String("fizz"), nil, ""}, {'"', String("buzz"), nil, ""}, {0, zeroToken, errMissingComma.withOffset(len64(` { "fizz" : "buzz" `)), ""}, @@ -451,7 +451,7 @@ var decoderErrorTestdata = []struct { in: ` { , } `, calls: []decoderMethodCall{ {'{', zeroValue, newInvalidCharacterError(",", `at start of string (expecting '"')`).withOffset(len64(` { `)), ""}, - {'{', ObjectStart, nil, ""}, + {'{', ObjectStart(), nil, ""}, {0, zeroToken, newInvalidCharacterError(",", `before next token`).withOffset(len64(` { `)), ""}, {0, zeroValue, newInvalidCharacterError(",", `before next token`).withOffset(len64(` { `)), ""}, }, @@ -461,7 +461,7 @@ var decoderErrorTestdata = []struct { in: ` { "fizz" : "buzz" , } `, calls: []decoderMethodCall{ {'{', zeroValue, newInvalidCharacterError("}", `at start of string (expecting '"')`).withOffset(len64(` { "fizz" : "buzz" , `)), ""}, - {'{', ObjectStart, nil, ""}, + {'{', ObjectStart(), nil, ""}, {'"', String("fizz"), nil, ""}, {'"', String("buzz"), nil, ""}, {0, zeroToken, newInvalidCharacterError(",", `before next token`).withOffset(len64(` { "fizz" : "buzz" `)), ""}, @@ -473,7 +473,7 @@ var decoderErrorTestdata = []struct { in: ` { null : null } `, calls: []decoderMethodCall{ {'{', zeroValue, newInvalidCharacterError("n", "at start of string (expecting '\"')").withOffset(len64(` { `)), ""}, - {'{', ObjectStart, nil, ""}, + {'{', ObjectStart(), nil, ""}, {'n', zeroToken, errMissingName.withOffset(len64(` { `)), ""}, {'n', zeroValue, errMissingName.withOffset(len64(` { `)), ""}, }, @@ -483,7 +483,7 @@ var decoderErrorTestdata = []struct { in: ` { false : false } `, calls: []decoderMethodCall{ {'{', zeroValue, newInvalidCharacterError("f", "at start of string (expecting '\"')").withOffset(len64(` { `)), ""}, - {'{', ObjectStart, nil, ""}, + {'{', ObjectStart(), nil, ""}, {'f', zeroToken, errMissingName.withOffset(len64(` { `)), ""}, {'f', zeroValue, errMissingName.withOffset(len64(` { `)), ""}, }, @@ -493,7 +493,7 @@ var decoderErrorTestdata = []struct { in: ` { true : true } `, calls: []decoderMethodCall{ {'{', zeroValue, newInvalidCharacterError("t", "at start of string (expecting '\"')").withOffset(len64(` { `)), ""}, - {'{', ObjectStart, nil, ""}, + {'{', ObjectStart(), nil, ""}, {'t', zeroToken, errMissingName.withOffset(len64(` { `)), ""}, {'t', zeroValue, errMissingName.withOffset(len64(` { `)), ""}, }, @@ -503,7 +503,7 @@ var decoderErrorTestdata = []struct { in: ` { 0 : 0 } `, calls: []decoderMethodCall{ {'{', zeroValue, newInvalidCharacterError("0", "at start of string (expecting '\"')").withOffset(len64(` { `)), ""}, - {'{', ObjectStart, nil, ""}, + {'{', ObjectStart(), nil, ""}, {'0', zeroToken, errMissingName.withOffset(len64(` { `)), ""}, {'0', zeroValue, errMissingName.withOffset(len64(` { `)), ""}, }, @@ -513,7 +513,7 @@ var decoderErrorTestdata = []struct { in: ` { {} : {} } `, calls: []decoderMethodCall{ {'{', zeroValue, newInvalidCharacterError("{", "at start of string (expecting '\"')").withOffset(len64(` { `)), ""}, - {'{', ObjectStart, nil, ""}, + {'{', ObjectStart(), nil, ""}, {'{', zeroToken, errMissingName.withOffset(len64(` { `)), ""}, {'{', zeroValue, errMissingName.withOffset(len64(` { `)), ""}, }, @@ -523,7 +523,7 @@ var decoderErrorTestdata = []struct { in: ` { [] : [] } `, calls: []decoderMethodCall{ {'{', zeroValue, newInvalidCharacterError("[", "at start of string (expecting '\"')").withOffset(len64(` { `)), ""}, - {'{', ObjectStart, nil, ""}, + {'{', ObjectStart(), nil, ""}, {'[', zeroToken, errMissingName.withOffset(len64(` { `)), ""}, {'[', zeroValue, errMissingName.withOffset(len64(` { `)), ""}, }, @@ -533,7 +533,7 @@ var decoderErrorTestdata = []struct { in: ` { ] `, calls: []decoderMethodCall{ {'{', zeroValue, newInvalidCharacterError("]", "at start of string (expecting '\"')").withOffset(len64(` { `)), ""}, - {'{', ObjectStart, nil, ""}, + {'{', ObjectStart(), nil, ""}, {']', zeroToken, errMismatchDelim.withOffset(len64(` { `)), ""}, {']', zeroValue, newInvalidCharacterError("]", "at start of value").withOffset(len64(` { `)), ""}, }, @@ -542,7 +542,7 @@ var decoderErrorTestdata = []struct { name: jsontest.Name("ValidObject/InvalidValue"), in: ` { } `, calls: []decoderMethodCall{ - {'{', ObjectStart, nil, ""}, + {'{', ObjectStart(), nil, ""}, {'}', zeroValue, newInvalidCharacterError("}", "at start of value").withOffset(len64(" { ")), ""}, }, wantOffset: len(` {`), @@ -550,12 +550,12 @@ var decoderErrorTestdata = []struct { name: jsontest.Name("ValidObject/UniqueNames"), in: `{"0":0,"1":1} `, calls: []decoderMethodCall{ - {'{', ObjectStart, nil, ""}, + {'{', ObjectStart(), nil, ""}, {'"', String("0"), nil, ""}, {'0', Uint(0), nil, ""}, {'"', String("1"), nil, ""}, {'0', Uint(1), nil, ""}, - {'}', ObjectEnd, nil, ""}, + {'}', ObjectEnd(), nil, ""}, }, wantOffset: len(`{"0":0,"1":1}`), }, { @@ -563,12 +563,12 @@ var decoderErrorTestdata = []struct { opts: []Options{AllowDuplicateNames(true)}, in: `{"0":0,"0":0} `, calls: []decoderMethodCall{ - {'{', ObjectStart, nil, ""}, + {'{', ObjectStart(), nil, ""}, {'"', String("0"), nil, ""}, {'0', Uint(0), nil, ""}, {'"', String("0"), nil, ""}, {'0', Uint(0), nil, ""}, - {'}', ObjectEnd, nil, ""}, + {'}', ObjectEnd(), nil, ""}, }, wantOffset: len(`{"0":0,"0":0}`), }, { @@ -576,13 +576,13 @@ var decoderErrorTestdata = []struct { in: `{"0":{},"1":{},"0":{}} `, calls: []decoderMethodCall{ {'{', zeroValue, newDuplicateNameError(`"0"`).withOffset(len64(`{"0":{},"1":{},`)), ""}, - {'{', ObjectStart, nil, ""}, + {'{', ObjectStart(), nil, ""}, {'"', String("0"), nil, ""}, - {'{', ObjectStart, nil, ""}, - {'}', ObjectEnd, nil, ""}, + {'{', ObjectStart(), nil, ""}, + {'}', ObjectEnd(), nil, ""}, {'"', String("1"), nil, ""}, - {'{', ObjectStart, nil, ""}, - {'}', ObjectEnd, nil, ""}, + {'{', ObjectStart(), nil, ""}, + {'}', ObjectEnd(), nil, ""}, {'"', zeroToken, newDuplicateNameError(`"0"`).withOffset(len64(`{"0":{},"1":{},`)), "/1"}, {'"', zeroValue, newDuplicateNameError(`"0"`).withOffset(len64(`{"0":{},"1":{},`)), "/1"}, }, @@ -592,7 +592,7 @@ var decoderErrorTestdata = []struct { in: `[`, calls: []decoderMethodCall{ {'[', zeroValue, io.ErrUnexpectedEOF, ""}, - {'[', ArrayStart, nil, ""}, + {'[', ArrayStart(), nil, ""}, {0, zeroToken, io.ErrUnexpectedEOF, ""}, {0, zeroValue, io.ErrUnexpectedEOF, ""}, }, @@ -602,7 +602,7 @@ var decoderErrorTestdata = []struct { in: `[0`, calls: []decoderMethodCall{ {'[', zeroValue, io.ErrUnexpectedEOF, ""}, - {'[', ArrayStart, nil, ""}, + {'[', ArrayStart(), nil, ""}, {'0', Uint(0), nil, ""}, {0, zeroToken, io.ErrUnexpectedEOF, ""}, {0, zeroValue, io.ErrUnexpectedEOF, ""}, @@ -613,7 +613,7 @@ var decoderErrorTestdata = []struct { in: `[0,`, calls: []decoderMethodCall{ {'[', zeroValue, io.ErrUnexpectedEOF, ""}, - {'[', ArrayStart, nil, ""}, + {'[', ArrayStart(), nil, ""}, {'0', Uint(0), nil, ""}, {0, zeroToken, io.ErrUnexpectedEOF, ""}, {0, zeroValue, io.ErrUnexpectedEOF, ""}, @@ -624,7 +624,7 @@ var decoderErrorTestdata = []struct { in: ` [ "fizz" "buzz" ] `, calls: []decoderMethodCall{ {'[', zeroValue, newInvalidCharacterError("\"", "after array value (expecting ',' or ']')").withOffset(len64(` [ "fizz" `)), ""}, - {'[', ArrayStart, nil, ""}, + {'[', ArrayStart(), nil, ""}, {'"', String("fizz"), nil, ""}, {0, zeroToken, errMissingComma.withOffset(len64(` [ "fizz" `)), ""}, {0, zeroValue, errMissingComma.withOffset(len64(` [ "fizz" `)), ""}, @@ -635,7 +635,7 @@ var decoderErrorTestdata = []struct { in: ` [ } `, calls: []decoderMethodCall{ {'[', zeroValue, newInvalidCharacterError("}", "at start of value").withOffset(len64(` [ `)), ""}, - {'[', ArrayStart, nil, ""}, + {'[', ArrayStart(), nil, ""}, {'}', zeroToken, errMismatchDelim.withOffset(len64(` { `)), ""}, {'}', zeroValue, newInvalidCharacterError("}", "at start of value").withOffset(len64(` [ `)), ""}, }, @@ -644,7 +644,7 @@ var decoderErrorTestdata = []struct { name: jsontest.Name("ValidArray/InvalidValue"), in: ` [ ] `, calls: []decoderMethodCall{ - {'[', ArrayStart, nil, ""}, + {'[', ArrayStart(), nil, ""}, {']', zeroValue, newInvalidCharacterError("]", "at start of value").withOffset(len64(" [ ")), ""}, }, wantOffset: len(` [`), @@ -661,7 +661,7 @@ var decoderErrorTestdata = []struct { name: jsontest.Name("InvalidDelim/AfterObjectStart"), in: `{:`, calls: []decoderMethodCall{ - {'{', ObjectStart, nil, ""}, + {'{', ObjectStart(), nil, ""}, {0, zeroToken, newInvalidCharacterError([]byte(":"), "before next token").withOffset(len64(`{`)), ""}, {0, zeroValue, newInvalidCharacterError([]byte(":"), "before next token").withOffset(len64(`{`)), ""}, }, @@ -670,7 +670,7 @@ var decoderErrorTestdata = []struct { name: jsontest.Name("InvalidDelim/AfterObjectName"), in: `{"",`, calls: []decoderMethodCall{ - {'{', ObjectStart, nil, ""}, + {'{', ObjectStart(), nil, ""}, {'"', String(""), nil, ""}, {0, zeroToken, errMissingColon.withOffset(len64(`{""`)), ""}, {0, zeroValue, errMissingColon.withOffset(len64(`{""`)), ""}, @@ -680,7 +680,7 @@ var decoderErrorTestdata = []struct { name: jsontest.Name("ValidDelim/AfterObjectName"), in: `{"":`, calls: []decoderMethodCall{ - {'{', ObjectStart, nil, ""}, + {'{', ObjectStart(), nil, ""}, {'"', String(""), nil, ""}, {0, zeroToken, io.ErrUnexpectedEOF, ""}, {0, zeroValue, io.ErrUnexpectedEOF, ""}, @@ -690,7 +690,7 @@ var decoderErrorTestdata = []struct { name: jsontest.Name("InvalidDelim/AfterObjectValue"), in: `{"":"":`, calls: []decoderMethodCall{ - {'{', ObjectStart, nil, ""}, + {'{', ObjectStart(), nil, ""}, {'"', String(""), nil, ""}, {'"', String(""), nil, ""}, {0, zeroToken, errMissingComma.withOffset(len64(`{"":""`)), ""}, @@ -701,7 +701,7 @@ var decoderErrorTestdata = []struct { name: jsontest.Name("ValidDelim/AfterObjectValue"), in: `{"":"",`, calls: []decoderMethodCall{ - {'{', ObjectStart, nil, ""}, + {'{', ObjectStart(), nil, ""}, {'"', String(""), nil, ""}, {'"', String(""), nil, ""}, {0, zeroToken, io.ErrUnexpectedEOF, ""}, @@ -712,7 +712,7 @@ var decoderErrorTestdata = []struct { name: jsontest.Name("InvalidDelim/AfterArrayStart"), in: `[,`, calls: []decoderMethodCall{ - {'[', ArrayStart, nil, ""}, + {'[', ArrayStart(), nil, ""}, {0, zeroToken, newInvalidCharacterError([]byte(","), "before next token").withOffset(len64(`[`)), ""}, {0, zeroValue, newInvalidCharacterError([]byte(","), "before next token").withOffset(len64(`[`)), ""}, }, @@ -721,7 +721,7 @@ var decoderErrorTestdata = []struct { name: jsontest.Name("InvalidDelim/AfterArrayValue"), in: `["":`, calls: []decoderMethodCall{ - {'[', ArrayStart, nil, ""}, + {'[', ArrayStart(), nil, ""}, {'"', String(""), nil, ""}, {0, zeroToken, errMissingComma.withOffset(len64(`[""`)), ""}, {0, zeroValue, errMissingComma.withOffset(len64(`[""`)), ""}, @@ -731,7 +731,7 @@ var decoderErrorTestdata = []struct { name: jsontest.Name("ValidDelim/AfterArrayValue"), in: `["",`, calls: []decoderMethodCall{ - {'[', ArrayStart, nil, ""}, + {'[', ArrayStart(), nil, ""}, {'"', String(""), nil, ""}, {0, zeroToken, io.ErrUnexpectedEOF, ""}, {0, zeroValue, io.ErrUnexpectedEOF, ""}, diff --git a/jsontext/encode_test.go b/jsontext/encode_test.go index 73f1391..3fd32eb 100644 --- a/jsontext/encode_test.go +++ b/jsontext/encode_test.go @@ -287,20 +287,20 @@ var encoderErrorTestdata = []struct { {Value(`{ 0 }`), newInvalidCharacterError("0", `at start of string (expecting '"')`).withOffset(len64(`{ `)), ""}, {Value(`{ {} }`), newInvalidCharacterError("{", `at start of string (expecting '"')`).withOffset(len64(`{ `)), ""}, {Value(`{ [] }`), newInvalidCharacterError("[", `at start of string (expecting '"')`).withOffset(len64(`{ `)), ""}, - {ObjectStart, nil, ""}, - {Null, errMissingName.withOffset(len64(`{`)), ""}, + {ObjectStart(), nil, ""}, + {Null(), errMissingName.withOffset(len64(`{`)), ""}, {Value(`null`), errMissingName.withOffset(len64(`{`)), ""}, - {False, errMissingName.withOffset(len64(`{`)), ""}, + {Bool(false), errMissingName.withOffset(len64(`{`)), ""}, {Value(`false`), errMissingName.withOffset(len64(`{`)), ""}, - {True, errMissingName.withOffset(len64(`{`)), ""}, + {Bool(true), errMissingName.withOffset(len64(`{`)), ""}, {Value(`true`), errMissingName.withOffset(len64(`{`)), ""}, {Uint(0), errMissingName.withOffset(len64(`{`)), ""}, {Value(`0`), errMissingName.withOffset(len64(`{`)), ""}, - {ObjectStart, errMissingName.withOffset(len64(`{`)), ""}, + {ObjectStart(), errMissingName.withOffset(len64(`{`)), ""}, {Value(`{}`), errMissingName.withOffset(len64(`{`)), ""}, - {ArrayStart, errMissingName.withOffset(len64(`{`)), ""}, + {ArrayStart(), errMissingName.withOffset(len64(`{`)), ""}, {Value(`[]`), errMissingName.withOffset(len64(`{`)), ""}, - {ObjectEnd, nil, ""}, + {ObjectEnd(), nil, ""}, }, wantOut: "{}\n", }, { @@ -313,21 +313,21 @@ var encoderErrorTestdata = []struct { calls: []encoderMethodCall{ {Value(` { ] `), newInvalidCharacterError("]", `at start of string (expecting '"')`).withOffset(len64(` { `)), ""}, {Value(` { "0":0 ] `), newInvalidCharacterError("]", `after object value (expecting ',' or '}')`).withOffset(len64(` { "0":0 `)), ""}, - {ObjectStart, nil, ""}, - {ArrayEnd, errMismatchDelim.withOffset(len64(`{`)), ""}, + {ObjectStart(), nil, ""}, + {ArrayEnd(), errMismatchDelim.withOffset(len64(`{`)), ""}, {Value(`]`), newInvalidCharacterError("]", "at start of value").withOffset(len64(`{`)), ""}, - {ObjectEnd, nil, ""}, + {ObjectEnd(), nil, ""}, }, wantOut: "{}\n", }, { name: jsontest.Name("ValidObject/UniqueNames"), calls: []encoderMethodCall{ - {ObjectStart, nil, ""}, + {ObjectStart(), nil, ""}, {String("0"), nil, ""}, {Uint(0), nil, ""}, {String("1"), nil, ""}, {Uint(1), nil, ""}, - {ObjectEnd, nil, ""}, + {ObjectEnd(), nil, ""}, {Value(` { "0" : 0 , "1" : 1 } `), nil, ""}, }, wantOut: `{"0":0,"1":1}` + "\n" + `{"0":0,"1":1}` + "\n", @@ -335,32 +335,32 @@ var encoderErrorTestdata = []struct { name: jsontest.Name("ValidObject/DuplicateNames"), opts: []Options{AllowDuplicateNames(true)}, calls: []encoderMethodCall{ - {ObjectStart, nil, ""}, + {ObjectStart(), nil, ""}, {String("0"), nil, ""}, {Uint(0), nil, ""}, {String("0"), nil, ""}, {Uint(0), nil, ""}, - {ObjectEnd, nil, ""}, + {ObjectEnd(), nil, ""}, {Value(` { "0" : 0 , "0" : 0 } `), nil, ""}, }, wantOut: `{"0":0,"0":0}` + "\n" + `{"0":0,"0":0}` + "\n", }, { name: jsontest.Name("InvalidObject/DuplicateNames"), calls: []encoderMethodCall{ - {ObjectStart, nil, ""}, + {ObjectStart(), nil, ""}, {String("0"), nil, ""}, - {ObjectStart, nil, ""}, - {ObjectEnd, nil, ""}, + {ObjectStart(), nil, ""}, + {ObjectEnd(), nil, ""}, {String("0"), newDuplicateNameError(`"0"`).withOffset(len64(`{"0":{},`)), "/0"}, {Value(`"0"`), newDuplicateNameError(`"0"`).withOffset(len64(`{"0":{},`)), "/0"}, {String("1"), nil, ""}, - {ObjectStart, nil, ""}, - {ObjectEnd, nil, ""}, + {ObjectStart(), nil, ""}, + {ObjectEnd(), nil, ""}, {String("0"), newDuplicateNameError(`"0"`).withOffset(len64(`{"0":{},"1":{},`)), "/1"}, {Value(`"0"`), newDuplicateNameError(`"0"`).withOffset(len64(`{"0":{},"1":{},`)), "/1"}, {String("1"), newDuplicateNameError(`"1"`).withOffset(len64(`{"0":{},"1":{},`)), "/1"}, {Value(`"1"`), newDuplicateNameError(`"1"`).withOffset(len64(`{"0":{},"1":{},`)), "/1"}, - {ObjectEnd, nil, ""}, + {ObjectEnd(), nil, ""}, {Value(` { "0" : 0 , "1" : 1 , "0" : 0 } `), newDuplicateNameError(`"0"`).withOffset(len64(`{"0":{},"1":{}}` + "\n" + ` { "0" : 0 , "1" : 1 , `)), ""}, }, wantOut: `{"0":{},"1":{}}` + "\n", @@ -388,10 +388,10 @@ var encoderErrorTestdata = []struct { name: jsontest.Name("InvalidArray/MismatchingDelim"), calls: []encoderMethodCall{ {Value(` [ } `), newInvalidCharacterError("}", `at start of value`).withOffset(len64(` [ `)), ""}, - {ArrayStart, nil, ""}, - {ObjectEnd, errMismatchDelim.withOffset(len64(`[`)), ""}, + {ArrayStart(), nil, ""}, + {ObjectEnd(), errMismatchDelim.withOffset(len64(`[`)), ""}, {Value(`}`), newInvalidCharacterError("}", "at start of value").withOffset(len64(`[`)), ""}, - {ArrayEnd, nil, ""}, + {ArrayEnd(), nil, ""}, }, wantOut: "[]\n", }} diff --git a/jsontext/token.go b/jsontext/token.go index 157a5bd..9c7f34d 100644 --- a/jsontext/token.go +++ b/jsontext/token.go @@ -86,14 +86,14 @@ type Token struct { // TODO: Does representing 1-byte delimiters as *decodeBuffer cause performance issues? var ( - Null Token = rawToken("null") - False Token = rawToken("false") - True Token = rawToken("true") + nullToken Token = rawToken("null") + falseToken Token = rawToken("false") + trueToken Token = rawToken("true") - ObjectStart Token = rawToken("{") - ObjectEnd Token = rawToken("}") - ArrayStart Token = rawToken("[") - ArrayEnd Token = rawToken("]") + objectStartToken Token = rawToken("{") + objectEndToken Token = rawToken("}") + arrayStartToken Token = rawToken("[") + arrayEndToken Token = rawToken("]") zeroString Token = rawToken(`""`) zeroNumber Token = rawToken(`0`) @@ -107,12 +107,15 @@ func rawToken(s string) Token { return Token{raw: &decodeBuffer{buf: []byte(s), prevStart: 0, prevEnd: len(s)}} } +// Null returns a Token representing a JSON null. +func Null() Token { return nullToken } + // Bool constructs a Token representing a JSON boolean. func Bool(b bool) Token { if b { - return True + return trueToken } - return False + return falseToken } // String constructs a Token representing a JSON string. @@ -125,6 +128,18 @@ func String(s string) Token { return Token{str: s} } +// ObjectStart returns a Token representing the start of a JSON object. +func ObjectStart() Token { return objectStartToken } + +// ObjectEnd returns a Token representing the end of a JSON object. +func ObjectEnd() Token { return objectEndToken } + +// ArrayStart returns a Token representing the start of a JSON array. +func ArrayStart() Token { return arrayStartToken } + +// ArrayEnd returns a Token representing the end of a JSON array. +func ArrayEnd() Token { return arrayEndToken } + // Float constructs a Token representing a JSON number. // The values NaN, +Inf, and -Inf will be represented // as a JSON string with the values "NaN", "Infinity", and "-Infinity". @@ -166,20 +181,20 @@ func (t Token) Clone() Token { // Avoid copying globals. if t.raw.prevStart == 0 { switch t.raw { - case Null.raw: - return Null - case False.raw: - return False - case True.raw: - return True - case ObjectStart.raw: - return ObjectStart - case ObjectEnd.raw: - return ObjectEnd - case ArrayStart.raw: - return ArrayStart - case ArrayEnd.raw: - return ArrayEnd + case nullToken.raw: + return nullToken + case falseToken.raw: + return falseToken + case trueToken.raw: + return trueToken + case objectStartToken.raw: + return objectStartToken + case objectEndToken.raw: + return objectEndToken + case arrayStartToken.raw: + return arrayStartToken + case arrayEndToken.raw: + return arrayEndToken } } @@ -197,9 +212,9 @@ func (t Token) Clone() Token { // It panics if the token kind is not a JSON boolean. func (t Token) Bool() bool { switch t.raw { - case True.raw: + case trueToken.raw: return true - case False.raw: + case falseToken.raw: return false default: panic("invalid JSON token kind: " + t.Kind().String()) diff --git a/jsontext/token_test.go b/jsontext/token_test.go index 457aefb..69604ca 100644 --- a/jsontext/token_test.go +++ b/jsontext/token_test.go @@ -44,15 +44,13 @@ func TestTokenAccessors(t *testing.T) { want token }{ {Token{}, token{String: ""}}, - {Null, token{String: "null", Kind: 'n'}}, - {False, token{Bool: false, String: "false", Kind: 'f'}}, - {True, token{Bool: true, String: "true", Kind: 't'}}, + {Null(), token{String: "null", Kind: 'n'}}, {Bool(false), token{Bool: false, String: "false", Kind: 'f'}}, {Bool(true), token{Bool: true, String: "true", Kind: 't'}}, - {ObjectStart, token{String: "{", Kind: '{'}}, - {ObjectEnd, token{String: "}", Kind: '}'}}, - {ArrayStart, token{String: "[", Kind: '['}}, - {ArrayEnd, token{String: "]", Kind: ']'}}, + {ObjectStart(), token{String: "{", Kind: '{'}}, + {ObjectEnd(), token{String: "}", Kind: '}'}}, + {ArrayStart(), token{String: "[", Kind: '['}}, + {ArrayEnd(), token{String: "]", Kind: ']'}}, {String(""), token{String: "", Kind: '"'}}, {String("hello, world!"), token{String: "hello, world!", Kind: '"'}}, {rawToken(`"hello, world!"`), token{String: "hello, world!", Kind: '"'}}, @@ -138,13 +136,13 @@ func TestTokenClone(t *testing.T) { wantExactRaw bool }{ {Token{}, true}, - {Null, true}, - {False, true}, - {True, true}, - {ObjectStart, true}, - {ObjectEnd, true}, - {ArrayStart, true}, - {ArrayEnd, true}, + {Null(), true}, + {Bool(false), true}, + {Bool(true), true}, + {ObjectStart(), true}, + {ObjectEnd(), true}, + {ArrayStart(), true}, + {ArrayEnd(), true}, {String("hello, world!"), true}, {rawToken(`"hello, world!"`), false}, {Float(3.14159), true},