From 66b8cb792aea0df6ab90642b8595a8c3ee72ca64 Mon Sep 17 00:00:00 2001 From: Masaaki Goshima Date: Thu, 17 Sep 2020 21:48:39 +0900 Subject: [PATCH 1/2] Keep reference of interface value --- decode_map.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/decode_map.go b/decode_map.go index 4e32ec8..01bca0a 100644 --- a/decode_map.go +++ b/decode_map.go @@ -28,11 +28,13 @@ func mapassign(t *rtype, m unsafe.Pointer, key, val unsafe.Pointer) func (d *mapDecoder) setKey(buf []byte, cursor int64, key interface{}) (int64, error) { header := (*interfaceHeader)(unsafe.Pointer(&key)) + d.dummy = header return d.keyDecoder.decode(buf, cursor, uintptr(header.ptr)) } func (d *mapDecoder) setValue(buf []byte, cursor int64, key interface{}) (int64, error) { header := (*interfaceHeader)(unsafe.Pointer(&key)) + d.dummy = header return d.valueDecoder.decode(buf, cursor, uintptr(header.ptr)) } From 9351afdb88a0283483e3a2f9674adbbea20a5a0d Mon Sep 17 00:00:00 2001 From: Masaaki Goshima Date: Thu, 17 Sep 2020 21:50:27 +0900 Subject: [PATCH 2/2] Fix pointer fields --- cmd/generator/main.go | 1 + decode_test.go | 2542 +++++++++++++++++++++++++++++++ encode_compile.go | 41 +- encode_optype.go | 1172 ++++++++------ encode_vm.go | 479 +++++- example_text_marshaling_test.go | 18 +- 6 files changed, 3729 insertions(+), 524 deletions(-) diff --git a/cmd/generator/main.go b/cmd/generator/main.go index c2f3185..1b4482e 100644 --- a/cmd/generator/main.go +++ b/cmd/generator/main.go @@ -277,6 +277,7 @@ func (t opType) fieldToStringTagField() opType { "StructFieldPtrAnonymousHeadOmitEmpty", "StructFieldPtrAnonymousHeadStringTag", "StructField", + "StructFieldPtr", "StructFieldOmitEmpty", "StructFieldStringTag", } { diff --git a/decode_test.go b/decode_test.go index 7c57b6b..a708b92 100644 --- a/decode_test.go +++ b/decode_test.go @@ -1,10 +1,18 @@ package json_test import ( + "bytes" + "encoding" + "errors" "fmt" + "image" + "math" + "math/big" "reflect" + "strconv" "strings" "testing" + "time" "github.com/goccy/go-json" ) @@ -345,3 +353,2537 @@ func Test_DecodeStream(t *testing.T) { assertErr(t, err) assertEq(t, "]", fmt.Sprint(tk), "]") } + +type T struct { + X string + Y int + Z int `json:"-"` +} + +type U struct { + Alphabet string `json:"alpha"` +} + +type V struct { + F1 interface{} + F2 int32 + F3 json.Number + F4 *VOuter +} + +type VOuter struct { + V V +} + +type W struct { + S SS +} + +type P struct { + PP PP +} + +type PP struct { + T T + Ts []T +} + +type SS string + +func (*SS) UnmarshalJSON(data []byte) error { + return &json.UnmarshalTypeError{Value: "number", Type: reflect.TypeOf(SS(""))} +} + +// ifaceNumAsFloat64/ifaceNumAsNumber are used to test unmarshaling with and +// without UseNumber +var ifaceNumAsFloat64 = map[string]interface{}{ + "k1": float64(1), + "k2": "s", + "k3": []interface{}{float64(1), float64(2.0), float64(3e-3)}, + "k4": map[string]interface{}{"kk1": "s", "kk2": float64(2)}, +} + +var ifaceNumAsNumber = map[string]interface{}{ + "k1": json.Number("1"), + "k2": "s", + "k3": []interface{}{json.Number("1"), json.Number("2.0"), json.Number("3e-3")}, + "k4": map[string]interface{}{"kk1": "s", "kk2": json.Number("2")}, +} + +type tx struct { + x int +} + +type u8 uint8 + +// A type that can unmarshal itself. + +type unmarshaler struct { + T bool +} + +func (u *unmarshaler) UnmarshalJSON(b []byte) error { + *u = unmarshaler{true} // All we need to see that UnmarshalJSON is called. + return nil +} + +type ustruct struct { + M unmarshaler +} + +var _ encoding.TextUnmarshaler = (*unmarshalerText)(nil) + +type ustructText struct { + M unmarshalerText +} + +// u8marshal is an integer type that can marshal/unmarshal itself. +type u8marshal uint8 + +func (u8 u8marshal) MarshalText() ([]byte, error) { + return []byte(fmt.Sprintf("u%d", u8)), nil +} + +var errMissingU8Prefix = errors.New("missing 'u' prefix") + +func (u8 *u8marshal) UnmarshalText(b []byte) error { + if !bytes.HasPrefix(b, []byte{'u'}) { + return errMissingU8Prefix + } + n, err := strconv.Atoi(string(b[1:])) + if err != nil { + return err + } + *u8 = u8marshal(n) + return nil +} + +var _ encoding.TextUnmarshaler = (*u8marshal)(nil) + +var ( + umtrue = unmarshaler{true} + umslice = []unmarshaler{{true}} + umstruct = ustruct{unmarshaler{true}} + + umtrueXY = unmarshalerText{"x", "y"} + umsliceXY = []unmarshalerText{{"x", "y"}} + umstructXY = ustructText{unmarshalerText{"x", "y"}} + + ummapXY = map[unmarshalerText]bool{{"x", "y"}: true} +) + +// Test data structures for anonymous fields. + +type Point struct { + Z int +} + +type Top struct { + Level0 int + Embed0 + *Embed0a + *Embed0b `json:"e,omitempty"` // treated as named + Embed0c `json:"-"` // ignored + Loop + Embed0p // has Point with X, Y, used + Embed0q // has Point with Z, used + embed // contains exported field +} + +type Embed0 struct { + Level1a int // overridden by Embed0a's Level1a with json tag + Level1b int // used because Embed0a's Level1b is renamed + Level1c int // used because Embed0a's Level1c is ignored + Level1d int // annihilated by Embed0a's Level1d + Level1e int `json:"x"` // annihilated by Embed0a.Level1e +} + +type Embed0a struct { + Level1a int `json:"Level1a,omitempty"` + Level1b int `json:"LEVEL1B,omitempty"` + Level1c int `json:"-"` + Level1d int // annihilated by Embed0's Level1d + Level1f int `json:"x"` // annihilated by Embed0's Level1e +} + +type Embed0b Embed0 + +type Embed0c Embed0 + +type Embed0p struct { + image.Point +} + +type Embed0q struct { + Point +} + +type embed struct { + Q int +} + +type Loop struct { + Loop1 int `json:",omitempty"` + Loop2 int `json:",omitempty"` + *Loop +} + +// From reflect test: +// The X in S6 and S7 annihilate, but they also block the X in S8.S9. +type S5 struct { + S6 + S7 + S8 +} + +type S6 struct { + X int +} + +type S7 S6 + +type S8 struct { + S9 +} + +type S9 struct { + X int + Y int +} + +// From reflect test: +// The X in S11.S6 and S12.S6 annihilate, but they also block the X in S13.S8.S9. +type S10 struct { + S11 + S12 + S13 +} + +type S11 struct { + S6 +} + +type S12 struct { + S6 +} + +type S13 struct { + S8 +} + +type Ambig struct { + // Given "hello", the first match should win. + First int `json:"HELLO"` + Second int `json:"Hello"` +} + +type XYZ struct { + X interface{} + Y interface{} + Z interface{} +} + +type unexportedWithMethods struct{} + +func (unexportedWithMethods) F() {} + +type byteWithMarshalJSON byte + +func (b byteWithMarshalJSON) MarshalJSON() ([]byte, error) { + return []byte(fmt.Sprintf(`"Z%.2x"`, byte(b))), nil +} + +func (b *byteWithMarshalJSON) UnmarshalJSON(data []byte) error { + if len(data) != 5 || data[0] != '"' || data[1] != 'Z' || data[4] != '"' { + return fmt.Errorf("bad quoted string") + } + i, err := strconv.ParseInt(string(data[2:4]), 16, 8) + if err != nil { + return fmt.Errorf("bad hex") + } + *b = byteWithMarshalJSON(i) + return nil +} + +type byteWithPtrMarshalJSON byte + +func (b *byteWithPtrMarshalJSON) MarshalJSON() ([]byte, error) { + return byteWithMarshalJSON(*b).MarshalJSON() +} + +func (b *byteWithPtrMarshalJSON) UnmarshalJSON(data []byte) error { + return (*byteWithMarshalJSON)(b).UnmarshalJSON(data) +} + +type byteWithMarshalText byte + +func (b byteWithMarshalText) MarshalText() ([]byte, error) { + return []byte(fmt.Sprintf(`Z%.2x`, byte(b))), nil +} + +func (b *byteWithMarshalText) UnmarshalText(data []byte) error { + if len(data) != 3 || data[0] != 'Z' { + return fmt.Errorf("bad quoted string") + } + i, err := strconv.ParseInt(string(data[1:3]), 16, 8) + if err != nil { + return fmt.Errorf("bad hex") + } + *b = byteWithMarshalText(i) + return nil +} + +type byteWithPtrMarshalText byte + +func (b *byteWithPtrMarshalText) MarshalText() ([]byte, error) { + return byteWithMarshalText(*b).MarshalText() +} + +func (b *byteWithPtrMarshalText) UnmarshalText(data []byte) error { + return (*byteWithMarshalText)(b).UnmarshalText(data) +} + +type intWithMarshalJSON int + +func (b intWithMarshalJSON) MarshalJSON() ([]byte, error) { + return []byte(fmt.Sprintf(`"Z%.2x"`, int(b))), nil +} + +func (b *intWithMarshalJSON) UnmarshalJSON(data []byte) error { + if len(data) != 5 || data[0] != '"' || data[1] != 'Z' || data[4] != '"' { + return fmt.Errorf("bad quoted string") + } + i, err := strconv.ParseInt(string(data[2:4]), 16, 8) + if err != nil { + return fmt.Errorf("bad hex") + } + *b = intWithMarshalJSON(i) + return nil +} + +type intWithPtrMarshalJSON int + +func (b *intWithPtrMarshalJSON) MarshalJSON() ([]byte, error) { + return intWithMarshalJSON(*b).MarshalJSON() +} + +func (b *intWithPtrMarshalJSON) UnmarshalJSON(data []byte) error { + return (*intWithMarshalJSON)(b).UnmarshalJSON(data) +} + +type intWithMarshalText int + +func (b intWithMarshalText) MarshalText() ([]byte, error) { + return []byte(fmt.Sprintf(`Z%.2x`, int(b))), nil +} + +func (b *intWithMarshalText) UnmarshalText(data []byte) error { + if len(data) != 3 || data[0] != 'Z' { + return fmt.Errorf("bad quoted string") + } + i, err := strconv.ParseInt(string(data[1:3]), 16, 8) + if err != nil { + return fmt.Errorf("bad hex") + } + *b = intWithMarshalText(i) + return nil +} + +type intWithPtrMarshalText int + +func (b *intWithPtrMarshalText) MarshalText() ([]byte, error) { + return intWithMarshalText(*b).MarshalText() +} + +func (b *intWithPtrMarshalText) UnmarshalText(data []byte) error { + return (*intWithMarshalText)(b).UnmarshalText(data) +} + +type mapStringToStringData struct { + Data map[string]string `json:"data"` +} + +type unmarshalTest struct { + in string + ptr interface{} // new(type) + out interface{} + err error + useNumber bool + golden bool + disallowUnknownFields bool +} + +type B struct { + B bool `json:",string"` +} + +type DoublePtr struct { + I **int + J **int +} + +var unmarshalTests = []unmarshalTest{ + // basic types + {in: `true`, ptr: new(bool), out: true}, + {in: `1`, ptr: new(int), out: 1}, + {in: `1.2`, ptr: new(float64), out: 1.2}, + {in: `-5`, ptr: new(int16), out: int16(-5)}, + {in: `2`, ptr: new(json.Number), out: json.Number("2"), useNumber: true}, + {in: `2`, ptr: new(json.Number), out: json.Number("2")}, + {in: `2`, ptr: new(interface{}), out: float64(2.0)}, + {in: `2`, ptr: new(interface{}), out: json.Number("2"), useNumber: true}, + {in: `"a\u1234"`, ptr: new(string), out: "a\u1234"}, + {in: `"http:\/\/"`, ptr: new(string), out: "http://"}, + {in: `"g-clef: \uD834\uDD1E"`, ptr: new(string), out: "g-clef: \U0001D11E"}, + {in: `"invalid: \uD834x\uDD1E"`, ptr: new(string), out: "invalid: \uFFFDx\uFFFD"}, + {in: "null", ptr: new(interface{}), out: nil}, + {in: `{"X": [1,2,3], "Y": 4}`, ptr: new(T), out: T{Y: 4}, err: &json.UnmarshalTypeError{"array", reflect.TypeOf(""), 7, "T", "X"}}, + {in: `{"X": 23}`, ptr: new(T), out: T{}, err: &json.UnmarshalTypeError{"number", reflect.TypeOf(""), 8, "T", "X"}}, {in: `{"x": 1}`, ptr: new(tx), out: tx{}}, + {in: `{"x": 1}`, ptr: new(tx), out: tx{}}, + {in: `{"x": 1}`, ptr: new(tx), err: fmt.Errorf("json: unknown field \"x\""), disallowUnknownFields: true}, + {in: `{"S": 23}`, ptr: new(W), out: W{}, err: &json.UnmarshalTypeError{"number", reflect.TypeOf(SS("")), 0, "W", "S"}}, + {in: `{"F1":1,"F2":2,"F3":3}`, ptr: new(V), out: V{F1: float64(1), F2: int32(2), F3: json.Number("3")}}, + {in: `{"F1":1,"F2":2,"F3":3}`, ptr: new(V), out: V{F1: json.Number("1"), F2: int32(2), F3: json.Number("3")}, useNumber: true}, + {in: `{"k1":1,"k2":"s","k3":[1,2.0,3e-3],"k4":{"kk1":"s","kk2":2}}`, ptr: new(interface{}), out: ifaceNumAsFloat64}, + {in: `{"k1":1,"k2":"s","k3":[1,2.0,3e-3],"k4":{"kk1":"s","kk2":2}}`, ptr: new(interface{}), out: ifaceNumAsNumber, useNumber: true}, + + // raw values with whitespace + {in: "\n true ", ptr: new(bool), out: true}, + {in: "\t 1 ", ptr: new(int), out: 1}, + {in: "\r 1.2 ", ptr: new(float64), out: 1.2}, + {in: "\t -5 \n", ptr: new(int16), out: int16(-5)}, + {in: "\t \"a\\u1234\" \n", ptr: new(string), out: "a\u1234"}, + + // Z has a "-" tag. + {in: `{"Y": 1, "Z": 2}`, ptr: new(T), out: T{Y: 1}}, + {in: `{"Y": 1, "Z": 2}`, ptr: new(T), err: fmt.Errorf("json: unknown field \"Z\""), disallowUnknownFields: true}, + + {in: `{"alpha": "abc", "alphabet": "xyz"}`, ptr: new(U), out: U{Alphabet: "abc"}}, + {in: `{"alpha": "abc", "alphabet": "xyz"}`, ptr: new(U), err: fmt.Errorf("json: unknown field \"alphabet\""), disallowUnknownFields: true}, + {in: `{"alpha": "abc"}`, ptr: new(U), out: U{Alphabet: "abc"}}, + {in: `{"alphabet": "xyz"}`, ptr: new(U), out: U{}}, + {in: `{"alphabet": "xyz"}`, ptr: new(U), err: fmt.Errorf("json: unknown field \"alphabet\""), disallowUnknownFields: true}, + + // syntax errors + {in: `{"X": "foo", "Y"}`, err: json.NewSyntaxError("invalid character '}' after object key", 17)}, + {in: `[1, 2, 3+]`, err: json.NewSyntaxError("invalid character '+' after array element", 9)}, + {in: `{"X":12x}`, err: json.NewSyntaxError("invalid character 'x' after object key:value pair", 8), useNumber: true}, + {in: `[2, 3`, err: json.NewSyntaxError("unexpected end of JSON input", 5)}, + {in: `{"F3": -}`, ptr: new(V), out: V{F3: json.Number("-")}, err: json.NewSyntaxError("invalid character '}' in numeric literal", 9)}, + + // raw value errors + {in: "\x01 42", err: json.NewSyntaxError("invalid character '\\x01' looking for beginning of value", 1)}, + {in: " 42 \x01", err: json.NewSyntaxError("invalid character '\\x01' after top-level value", 5)}, + {in: "\x01 true", err: json.NewSyntaxError("invalid character '\\x01' looking for beginning of value", 1)}, + {in: " false \x01", err: json.NewSyntaxError("invalid character '\\x01' after top-level value", 8)}, + {in: "\x01 1.2", err: json.NewSyntaxError("invalid character '\\x01' looking for beginning of value", 1)}, + {in: " 3.4 \x01", err: json.NewSyntaxError("invalid character '\\x01' after top-level value", 6)}, + {in: "\x01 \"string\"", err: json.NewSyntaxError("invalid character '\\x01' looking for beginning of value", 1)}, + {in: " \"string\" \x01", err: json.NewSyntaxError("invalid character '\\x01' after top-level value", 11)}, + + // array tests + {in: `[1, 2, 3]`, ptr: new([3]int), out: [3]int{1, 2, 3}}, + {in: `[1, 2, 3]`, ptr: new([1]int), out: [1]int{1}}, + {in: `[1, 2, 3]`, ptr: new([5]int), out: [5]int{1, 2, 3, 0, 0}}, + {in: `[1, 2, 3]`, ptr: new(MustNotUnmarshalJSON), err: errors.New("MustNotUnmarshalJSON was used")}, + + // empty array to interface test + {in: `[]`, ptr: new([]interface{}), out: []interface{}{}}, + {in: `null`, ptr: new([]interface{}), out: []interface{}(nil)}, + {in: `{"T":[]}`, ptr: new(map[string]interface{}), out: map[string]interface{}{"T": []interface{}{}}}, + {in: `{"T":null}`, ptr: new(map[string]interface{}), out: map[string]interface{}{"T": interface{}(nil)}}, + + // composite tests + {in: allValueIndent, ptr: new(All), out: allValue}, + {in: allValueCompact, ptr: new(All), out: allValue}, + {in: allValueIndent, ptr: new(*All), out: &allValue}, + {in: allValueCompact, ptr: new(*All), out: &allValue}, + {in: pallValueIndent, ptr: new(All), out: pallValue}, + {in: pallValueCompact, ptr: new(All), out: pallValue}, + {in: pallValueIndent, ptr: new(*All), out: &pallValue}, + {in: pallValueCompact, ptr: new(*All), out: &pallValue}, + + // unmarshal interface test + {in: `{"T":false}`, ptr: new(unmarshaler), out: umtrue}, // use "false" so test will fail if custom unmarshaler is not called + {in: `{"T":false}`, ptr: new(*unmarshaler), out: &umtrue}, + {in: `[{"T":false}]`, ptr: new([]unmarshaler), out: umslice}, + {in: `[{"T":false}]`, ptr: new(*[]unmarshaler), out: &umslice}, + {in: `{"M":{"T":"x:y"}}`, ptr: new(ustruct), out: umstruct}, + + // UnmarshalText interface test + {in: `"x:y"`, ptr: new(unmarshalerText), out: umtrueXY}, + {in: `"x:y"`, ptr: new(*unmarshalerText), out: &umtrueXY}, + {in: `["x:y"]`, ptr: new([]unmarshalerText), out: umsliceXY}, + {in: `["x:y"]`, ptr: new(*[]unmarshalerText), out: &umsliceXY}, + {in: `{"M":"x:y"}`, ptr: new(ustructText), out: umstructXY}, + + // integer-keyed map test + { + in: `{"-1":"a","0":"b","1":"c"}`, + ptr: new(map[int]string), + out: map[int]string{-1: "a", 0: "b", 1: "c"}, + }, + { + in: `{"0":"a","10":"c","9":"b"}`, + ptr: new(map[u8]string), + out: map[u8]string{0: "a", 9: "b", 10: "c"}, + }, + { + in: `{"-9223372036854775808":"min","9223372036854775807":"max"}`, + ptr: new(map[int64]string), + out: map[int64]string{math.MinInt64: "min", math.MaxInt64: "max"}, + }, + { + in: `{"18446744073709551615":"max"}`, + ptr: new(map[uint64]string), + out: map[uint64]string{math.MaxUint64: "max"}, + }, + { + in: `{"0":false,"10":true}`, + ptr: new(map[uintptr]bool), + out: map[uintptr]bool{0: false, 10: true}, + }, + + // Check that MarshalText and UnmarshalText take precedence + // over default integer handling in map keys. + { + in: `{"u2":4}`, + ptr: new(map[u8marshal]int), + out: map[u8marshal]int{2: 4}, + }, + { + in: `{"2":4}`, + ptr: new(map[u8marshal]int), + err: errMissingU8Prefix, + }, + + // integer-keyed map errors + { + in: `{"abc":"abc"}`, + ptr: new(map[int]string), + err: &json.UnmarshalTypeError{Value: "number abc", Type: reflect.TypeOf(0), Offset: 2}, + }, + { + in: `{"256":"abc"}`, + ptr: new(map[uint8]string), + err: &json.UnmarshalTypeError{Value: "number 256", Type: reflect.TypeOf(uint8(0)), Offset: 2}, + }, + { + in: `{"128":"abc"}`, + ptr: new(map[int8]string), + err: &json.UnmarshalTypeError{Value: "number 128", Type: reflect.TypeOf(int8(0)), Offset: 2}, + }, + { + in: `{"-1":"abc"}`, + ptr: new(map[uint8]string), + err: &json.UnmarshalTypeError{Value: "number -1", Type: reflect.TypeOf(uint8(0)), Offset: 2}, + }, + { + in: `{"F":{"a":2,"3":4}}`, + ptr: new(map[string]map[int]int), + err: &json.UnmarshalTypeError{Value: "number a", Type: reflect.TypeOf(int(0)), Offset: 7}, + }, + { + in: `{"F":{"a":2,"3":4}}`, + ptr: new(map[string]map[uint]int), + err: &json.UnmarshalTypeError{Value: "number a", Type: reflect.TypeOf(uint(0)), Offset: 7}, + }, + + // Map keys can be encoding.TextUnmarshalers. + {in: `{"x:y":true}`, ptr: new(map[unmarshalerText]bool), out: ummapXY}, + // If multiple values for the same key exists, only the most recent value is used. + {in: `{"x:y":false,"x:y":true}`, ptr: new(map[unmarshalerText]bool), out: ummapXY}, + + { + in: `{ + "Level0": 1, + "Level1b": 2, + "Level1c": 3, + "x": 4, + "Level1a": 5, + "LEVEL1B": 6, + "e": { + "Level1a": 8, + "Level1b": 9, + "Level1c": 10, + "Level1d": 11, + "x": 12 + }, + "Loop1": 13, + "Loop2": 14, + "X": 15, + "Y": 16, + "Z": 17, + "Q": 18 + }`, + ptr: new(Top), + out: Top{ + Level0: 1, + Embed0: Embed0{ + Level1b: 2, + Level1c: 3, + }, + Embed0a: &Embed0a{ + Level1a: 5, + Level1b: 6, + }, + Embed0b: &Embed0b{ + Level1a: 8, + Level1b: 9, + Level1c: 10, + Level1d: 11, + Level1e: 12, + }, + Loop: Loop{ + Loop1: 13, + Loop2: 14, + }, + Embed0p: Embed0p{ + Point: image.Point{X: 15, Y: 16}, + }, + Embed0q: Embed0q{ + Point: Point{Z: 17}, + }, + embed: embed{ + Q: 18, + }, + }, + }, + { + in: `{"hello": 1}`, + ptr: new(Ambig), + out: Ambig{First: 1}, + }, + + { + in: `{"X": 1,"Y":2}`, + ptr: new(S5), + out: S5{S8: S8{S9: S9{Y: 2}}}, + }, + { + in: `{"X": 1,"Y":2}`, + ptr: new(S5), + err: fmt.Errorf("json: unknown field \"X\""), + disallowUnknownFields: true, + }, + { + in: `{"X": 1,"Y":2}`, + ptr: new(S10), + out: S10{S13: S13{S8: S8{S9: S9{Y: 2}}}}, + }, + { + in: `{"X": 1,"Y":2}`, + ptr: new(S10), + err: fmt.Errorf("json: unknown field \"X\""), + disallowUnknownFields: true, + }, + { + in: `{"I": 0, "I": null, "J": null}`, + ptr: new(DoublePtr), + out: DoublePtr{I: nil, J: nil}, + }, + + // invalid UTF-8 is coerced to valid UTF-8. + { + in: "\"hello\xffworld\"", + ptr: new(string), + out: "hello\ufffdworld", + }, + { + in: "\"hello\xc2\xc2world\"", + ptr: new(string), + out: "hello\ufffd\ufffdworld", + }, + { + in: "\"hello\xc2\xffworld\"", + ptr: new(string), + out: "hello\ufffd\ufffdworld", + }, + { + in: "\"hello\\ud800world\"", + ptr: new(string), + out: "hello\ufffdworld", + }, + { + in: "\"hello\\ud800\\ud800world\"", + ptr: new(string), + out: "hello\ufffd\ufffdworld", + }, + { + in: "\"hello\\ud800\\ud800world\"", + ptr: new(string), + out: "hello\ufffd\ufffdworld", + }, + { + in: "\"hello\xed\xa0\x80\xed\xb0\x80world\"", + ptr: new(string), + out: "hello\ufffd\ufffd\ufffd\ufffd\ufffd\ufffdworld", + }, + + // Used to be issue 8305, but time.Time implements encoding.TextUnmarshaler so this works now. + { + in: `{"2009-11-10T23:00:00Z": "hello world"}`, + ptr: new(map[time.Time]string), + out: map[time.Time]string{time.Date(2009, 11, 10, 23, 0, 0, 0, time.UTC): "hello world"}, + }, + + // issue 8305 + { + in: `{"2009-11-10T23:00:00Z": "hello world"}`, + ptr: new(map[Point]string), + err: &json.UnmarshalTypeError{Value: "object", Type: reflect.TypeOf(map[Point]string{}), Offset: 1}, + }, + { + in: `{"asdf": "hello world"}`, + ptr: new(map[unmarshaler]string), + err: &json.UnmarshalTypeError{Value: "object", Type: reflect.TypeOf(map[unmarshaler]string{}), Offset: 1}, + }, + + // related to issue 13783. + // Go 1.7 changed marshaling a slice of typed byte to use the methods on the byte type, + // similar to marshaling a slice of typed int. + // These tests check that, assuming the byte type also has valid decoding methods, + // either the old base64 string encoding or the new per-element encoding can be + // successfully unmarshaled. The custom unmarshalers were accessible in earlier + // versions of Go, even though the custom marshaler was not. + { + in: `"AQID"`, + ptr: new([]byteWithMarshalJSON), + out: []byteWithMarshalJSON{1, 2, 3}, + }, + { + in: `["Z01","Z02","Z03"]`, + ptr: new([]byteWithMarshalJSON), + out: []byteWithMarshalJSON{1, 2, 3}, + golden: true, + }, + { + in: `"AQID"`, + ptr: new([]byteWithMarshalText), + out: []byteWithMarshalText{1, 2, 3}, + }, + { + in: `["Z01","Z02","Z03"]`, + ptr: new([]byteWithMarshalText), + out: []byteWithMarshalText{1, 2, 3}, + golden: true, + }, + { + in: `"AQID"`, + ptr: new([]byteWithPtrMarshalJSON), + out: []byteWithPtrMarshalJSON{1, 2, 3}, + }, + { + in: `["Z01","Z02","Z03"]`, + ptr: new([]byteWithPtrMarshalJSON), + out: []byteWithPtrMarshalJSON{1, 2, 3}, + golden: true, + }, + { + in: `"AQID"`, + ptr: new([]byteWithPtrMarshalText), + out: []byteWithPtrMarshalText{1, 2, 3}, + }, + { + in: `["Z01","Z02","Z03"]`, + ptr: new([]byteWithPtrMarshalText), + out: []byteWithPtrMarshalText{1, 2, 3}, + golden: true, + }, + + // ints work with the marshaler but not the base64 []byte case + { + in: `["Z01","Z02","Z03"]`, + ptr: new([]intWithMarshalJSON), + out: []intWithMarshalJSON{1, 2, 3}, + golden: true, + }, + { + in: `["Z01","Z02","Z03"]`, + ptr: new([]intWithMarshalText), + out: []intWithMarshalText{1, 2, 3}, + golden: true, + }, + { + in: `["Z01","Z02","Z03"]`, + ptr: new([]intWithPtrMarshalJSON), + out: []intWithPtrMarshalJSON{1, 2, 3}, + golden: true, + }, + { + in: `["Z01","Z02","Z03"]`, + ptr: new([]intWithPtrMarshalText), + out: []intWithPtrMarshalText{1, 2, 3}, + golden: true, + }, + + {in: `0.000001`, ptr: new(float64), out: 0.000001, golden: true}, + {in: `1e-7`, ptr: new(float64), out: 1e-7, golden: true}, + {in: `100000000000000000000`, ptr: new(float64), out: 100000000000000000000.0, golden: true}, + {in: `1e+21`, ptr: new(float64), out: 1e21, golden: true}, + {in: `-0.000001`, ptr: new(float64), out: -0.000001, golden: true}, + {in: `-1e-7`, ptr: new(float64), out: -1e-7, golden: true}, + {in: `-100000000000000000000`, ptr: new(float64), out: -100000000000000000000.0, golden: true}, + {in: `-1e+21`, ptr: new(float64), out: -1e21, golden: true}, + {in: `999999999999999900000`, ptr: new(float64), out: 999999999999999900000.0, golden: true}, + {in: `9007199254740992`, ptr: new(float64), out: 9007199254740992.0, golden: true}, + {in: `9007199254740993`, ptr: new(float64), out: 9007199254740992.0, golden: false}, + + { + in: `{"V": {"F2": "hello"}}`, + ptr: new(VOuter), + err: &json.UnmarshalTypeError{ + Value: "string", + Struct: "V", + Field: "V.F2", + Type: reflect.TypeOf(int32(0)), + Offset: 20, + }, + }, + { + in: `{"V": {"F4": {}, "F2": "hello"}}`, + ptr: new(VOuter), + err: &json.UnmarshalTypeError{ + Value: "string", + Struct: "V", + Field: "V.F2", + Type: reflect.TypeOf(int32(0)), + Offset: 30, + }, + }, + + // issue 15146. + // invalid inputs in wrongStringTests below. + {in: `{"B":"true"}`, ptr: new(B), out: B{true}, golden: true}, + {in: `{"B":"false"}`, ptr: new(B), out: B{false}, golden: true}, + {in: `{"B": "maybe"}`, ptr: new(B), err: errors.New(`json: invalid use of ,string struct tag, trying to unmarshal "maybe" into bool`)}, + {in: `{"B": "tru"}`, ptr: new(B), err: errors.New(`json: invalid use of ,string struct tag, trying to unmarshal "tru" into bool`)}, + {in: `{"B": "False"}`, ptr: new(B), err: errors.New(`json: invalid use of ,string struct tag, trying to unmarshal "False" into bool`)}, + {in: `{"B": "null"}`, ptr: new(B), out: B{false}}, + {in: `{"B": "nul"}`, ptr: new(B), err: errors.New(`json: invalid use of ,string struct tag, trying to unmarshal "nul" into bool`)}, + {in: `{"B": [2, 3]}`, ptr: new(B), err: errors.New(`json: invalid use of ,string struct tag, trying to unmarshal unquoted value into bool`)}, + + // additional tests for disallowUnknownFields + { + in: `{ + "Level0": 1, + "Level1b": 2, + "Level1c": 3, + "x": 4, + "Level1a": 5, + "LEVEL1B": 6, + "e": { + "Level1a": 8, + "Level1b": 9, + "Level1c": 10, + "Level1d": 11, + "x": 12 + }, + "Loop1": 13, + "Loop2": 14, + "X": 15, + "Y": 16, + "Z": 17, + "Q": 18, + "extra": true + }`, + ptr: new(Top), + err: fmt.Errorf("json: unknown field \"extra\""), + disallowUnknownFields: true, + }, + { + in: `{ + "Level0": 1, + "Level1b": 2, + "Level1c": 3, + "x": 4, + "Level1a": 5, + "LEVEL1B": 6, + "e": { + "Level1a": 8, + "Level1b": 9, + "Level1c": 10, + "Level1d": 11, + "x": 12, + "extra": null + }, + "Loop1": 13, + "Loop2": 14, + "X": 15, + "Y": 16, + "Z": 17, + "Q": 18 + }`, + ptr: new(Top), + err: fmt.Errorf("json: unknown field \"extra\""), + disallowUnknownFields: true, + }, + // issue 26444 + // UnmarshalTypeError without field & struct values + { + in: `{"data":{"test1": "bob", "test2": 123}}`, + ptr: new(mapStringToStringData), + err: &json.UnmarshalTypeError{Value: "number", Type: reflect.TypeOf(""), Offset: 37, Struct: "mapStringToStringData", Field: "data"}, + }, + { + in: `{"data":{"test1": 123, "test2": "bob"}}`, + ptr: new(mapStringToStringData), + err: &json.UnmarshalTypeError{Value: "number", Type: reflect.TypeOf(""), Offset: 21, Struct: "mapStringToStringData", Field: "data"}, + }, + + // trying to decode JSON arrays or objects via TextUnmarshaler + { + in: `[1, 2, 3]`, + ptr: new(MustNotUnmarshalText), + err: &json.UnmarshalTypeError{Value: "array", Type: reflect.TypeOf(&MustNotUnmarshalText{}), Offset: 1}, + }, + { + in: `{"foo": "bar"}`, + ptr: new(MustNotUnmarshalText), + err: &json.UnmarshalTypeError{Value: "object", Type: reflect.TypeOf(&MustNotUnmarshalText{}), Offset: 1}, + }, + // #22369 + { + in: `{"PP": {"T": {"Y": "bad-type"}}}`, + ptr: new(P), + err: &json.UnmarshalTypeError{ + Value: "string", + Struct: "T", + Field: "PP.T.Y", + Type: reflect.TypeOf(int(0)), + Offset: 29, + }, + }, + { + in: `{"Ts": [{"Y": 1}, {"Y": 2}, {"Y": "bad-type"}]}`, + ptr: new(PP), + err: &json.UnmarshalTypeError{ + Value: "string", + Struct: "T", + Field: "Ts.Y", + Type: reflect.TypeOf(int(0)), + Offset: 29, + }, + }, + // #14702 + { + in: `invalid`, + ptr: new(json.Number), + err: json.NewSyntaxError( + "invalid character 'i' looking for beginning of value", + 1, + ), + }, + { + in: `"invalid"`, + ptr: new(json.Number), + err: fmt.Errorf("json: invalid number literal, trying to unmarshal %q into Number", `"invalid"`), + }, + { + in: `{"A":"invalid"}`, + ptr: new(struct{ A json.Number }), + err: fmt.Errorf("json: invalid number literal, trying to unmarshal %q into Number", `"invalid"`), + }, + { + in: `{"A":"invalid"}`, + ptr: new(struct { + A json.Number `json:",string"` + }), + err: fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into json.Number", `invalid`), + }, + { + in: `{"A":"invalid"}`, + ptr: new(map[string]json.Number), + err: fmt.Errorf("json: invalid number literal, trying to unmarshal %q into Number", `"invalid"`), + }, +} + +type All struct { + Bool bool + Int int + Int8 int8 + Int16 int16 + Int32 int32 + Int64 int64 + Uint uint + Uint8 uint8 + Uint16 uint16 + Uint32 uint32 + Uint64 uint64 + Uintptr uintptr + Float32 float32 + Float64 float64 + + Foo string `json:"bar"` + Foo2 string `json:"bar2,dummyopt"` + + IntStr int64 `json:",string"` + UintptrStr uintptr `json:",string"` + + PBool *bool + PInt *int + PInt8 *int8 + PInt16 *int16 + PInt32 *int32 + PInt64 *int64 + PUint *uint + PUint8 *uint8 + PUint16 *uint16 + PUint32 *uint32 + PUint64 *uint64 + PUintptr *uintptr + PFloat32 *float32 + PFloat64 *float64 + + String string + PString *string + + Map map[string]Small + MapP map[string]*Small + PMap *map[string]Small + PMapP *map[string]*Small + + EmptyMap map[string]Small + NilMap map[string]Small + + Slice []Small + SliceP []*Small + PSlice *[]Small + PSliceP *[]*Small + + EmptySlice []Small + NilSlice []Small + + StringSlice []string + ByteSlice []byte + + Small Small + PSmall *Small + PPSmall **Small + + Interface interface{} + PInterface *interface{} + + unexported int +} + +type Small struct { + Tag string +} + +var allValue = All{ + Bool: true, + Int: 2, + Int8: 3, + Int16: 4, + Int32: 5, + Int64: 6, + Uint: 7, + Uint8: 8, + Uint16: 9, + Uint32: 10, + Uint64: 11, + Uintptr: 12, + Float32: 14.1, + Float64: 15.1, + Foo: "foo", + Foo2: "foo2", + IntStr: 42, + UintptrStr: 44, + String: "16", + Map: map[string]Small{ + "17": {Tag: "tag17"}, + "18": {Tag: "tag18"}, + }, + MapP: map[string]*Small{ + "19": {Tag: "tag19"}, + "20": nil, + }, + EmptyMap: map[string]Small{}, + Slice: []Small{{Tag: "tag20"}, {Tag: "tag21"}}, + SliceP: []*Small{{Tag: "tag22"}, nil, {Tag: "tag23"}}, + EmptySlice: []Small{}, + StringSlice: []string{"str24", "str25", "str26"}, + ByteSlice: []byte{27, 28, 29}, + Small: Small{Tag: "tag30"}, + PSmall: &Small{Tag: "tag31"}, + Interface: 5.2, +} + +var pallValue = All{ + PBool: &allValue.Bool, + PInt: &allValue.Int, + PInt8: &allValue.Int8, + PInt16: &allValue.Int16, + PInt32: &allValue.Int32, + PInt64: &allValue.Int64, + PUint: &allValue.Uint, + PUint8: &allValue.Uint8, + PUint16: &allValue.Uint16, + PUint32: &allValue.Uint32, + PUint64: &allValue.Uint64, + PUintptr: &allValue.Uintptr, + PFloat32: &allValue.Float32, + PFloat64: &allValue.Float64, + PString: &allValue.String, + PMap: &allValue.Map, + PMapP: &allValue.MapP, + PSlice: &allValue.Slice, + PSliceP: &allValue.SliceP, + PPSmall: &allValue.PSmall, + PInterface: &allValue.Interface, +} + +var allValueIndent = `{ + "Bool": true, + "Int": 2, + "Int8": 3, + "Int16": 4, + "Int32": 5, + "Int64": 6, + "Uint": 7, + "Uint8": 8, + "Uint16": 9, + "Uint32": 10, + "Uint64": 11, + "Uintptr": 12, + "Float32": 14.1, + "Float64": 15.1, + "bar": "foo", + "bar2": "foo2", + "IntStr": "42", + "UintptrStr": "44", + "PBool": null, + "PInt": null, + "PInt8": null, + "PInt16": null, + "PInt32": null, + "PInt64": null, + "PUint": null, + "PUint8": null, + "PUint16": null, + "PUint32": null, + "PUint64": null, + "PUintptr": null, + "PFloat32": null, + "PFloat64": null, + "String": "16", + "PString": null, + "Map": { + "17": { + "Tag": "tag17" + }, + "18": { + "Tag": "tag18" + } + }, + "MapP": { + "19": { + "Tag": "tag19" + }, + "20": null + }, + "PMap": null, + "PMapP": null, + "EmptyMap": {}, + "NilMap": null, + "Slice": [ + { + "Tag": "tag20" + }, + { + "Tag": "tag21" + } + ], + "SliceP": [ + { + "Tag": "tag22" + }, + null, + { + "Tag": "tag23" + } + ], + "PSlice": null, + "PSliceP": null, + "EmptySlice": [], + "NilSlice": null, + "StringSlice": [ + "str24", + "str25", + "str26" + ], + "ByteSlice": "Gxwd", + "Small": { + "Tag": "tag30" + }, + "PSmall": { + "Tag": "tag31" + }, + "PPSmall": null, + "Interface": 5.2, + "PInterface": null +}` + +var allValueCompact = strings.Map(noSpace, allValueIndent) + +var pallValueIndent = `{ + "Bool": false, + "Int": 0, + "Int8": 0, + "Int16": 0, + "Int32": 0, + "Int64": 0, + "Uint": 0, + "Uint8": 0, + "Uint16": 0, + "Uint32": 0, + "Uint64": 0, + "Uintptr": 0, + "Float32": 0, + "Float64": 0, + "bar": "", + "bar2": "", + "IntStr": "0", + "UintptrStr": "0", + "PBool": true, + "PInt": 2, + "PInt8": 3, + "PInt16": 4, + "PInt32": 5, + "PInt64": 6, + "PUint": 7, + "PUint8": 8, + "PUint16": 9, + "PUint32": 10, + "PUint64": 11, + "PUintptr": 12, + "PFloat32": 14.1, + "PFloat64": 15.1, + "String": "", + "PString": "16", + "Map": null, + "MapP": null, + "PMap": { + "17": { + "Tag": "tag17" + }, + "18": { + "Tag": "tag18" + } + }, + "PMapP": { + "19": { + "Tag": "tag19" + }, + "20": null + }, + "EmptyMap": null, + "NilMap": null, + "Slice": null, + "SliceP": null, + "PSlice": [ + { + "Tag": "tag20" + }, + { + "Tag": "tag21" + } + ], + "PSliceP": [ + { + "Tag": "tag22" + }, + null, + { + "Tag": "tag23" + } + ], + "EmptySlice": null, + "NilSlice": null, + "StringSlice": null, + "ByteSlice": null, + "Small": { + "Tag": "" + }, + "PSmall": null, + "PPSmall": { + "Tag": "tag31" + }, + "Interface": null, + "PInterface": 5.2 +}` + +var pallValueCompact = strings.Map(noSpace, pallValueIndent) + +type NullTest struct { + Bool bool + Int int + Int8 int8 + Int16 int16 + Int32 int32 + Int64 int64 + Uint uint + Uint8 uint8 + Uint16 uint16 + Uint32 uint32 + Uint64 uint64 + Float32 float32 + Float64 float64 + String string + PBool *bool + Map map[string]string + Slice []string + Interface interface{} + + PRaw *json.RawMessage + PTime *time.Time + PBigInt *big.Int + PText *MustNotUnmarshalText + PBuffer *bytes.Buffer // has methods, just not relevant ones + PStruct *struct{} + + Raw json.RawMessage + Time time.Time + BigInt big.Int + Text MustNotUnmarshalText + Buffer bytes.Buffer + Struct struct{} +} + +type MustNotUnmarshalJSON struct{} + +func (x MustNotUnmarshalJSON) UnmarshalJSON(data []byte) error { + return errors.New("MustNotUnmarshalJSON was used") +} + +type MustNotUnmarshalText struct{} + +func (x MustNotUnmarshalText) UnmarshalText(text []byte) error { + return errors.New("MustNotUnmarshalText was used") +} + +func isSpace(c byte) bool { + return c <= ' ' && (c == ' ' || c == '\t' || c == '\r' || c == '\n') +} + +func noSpace(c rune) rune { + if isSpace(byte(c)) { //only used for ascii + return -1 + } + return c +} + +var badUTF8 = []struct { + in, out string +}{ + {"hello\xffworld", `"hello\ufffdworld"`}, + {"", `""`}, + {"\xff", `"\ufffd"`}, + {"\xff\xff", `"\ufffd\ufffd"`}, + {"a\xffb", `"a\ufffdb"`}, + {"\xe6\x97\xa5\xe6\x9c\xac\xff\xaa\x9e", `"日本\ufffd\ufffd\ufffd"`}, +} + +func TestMarshalAllValue(t *testing.T) { + b, err := json.Marshal(allValue) + if err != nil { + t.Fatalf("Marshal allValue: %v", err) + } + if string(b) != allValueCompact { + t.Errorf("Marshal allValueCompact") + diff(t, b, []byte(allValueCompact)) + return + } + + b, err = json.Marshal(pallValue) + if err != nil { + t.Fatalf("Marshal pallValue: %v", err) + } + if string(b) != pallValueCompact { + t.Errorf("Marshal pallValueCompact") + diff(t, b, []byte(pallValueCompact)) + return + } +} + +func TestMarshalBadUTF8(t *testing.T) { + for _, tt := range badUTF8 { + b, err := json.Marshal(tt.in) + if string(b) != tt.out || err != nil { + t.Errorf("Marshal(%q) = %#q, %v, want %#q, nil", tt.in, b, err, tt.out) + } + } +} + +/* +func TestMarshalNumberZeroVal(t *testing.T) { + var n json.Number + out, err := json.Marshal(n) + if err != nil { + t.Fatal(err) + } + outStr := string(out) + if outStr != "0" { + t.Fatalf("Invalid zero val for Number: %q", outStr) + } +} + +func TestMarshalEmbeds(t *testing.T) { + top := &Top{ + Level0: 1, + Embed0: Embed0{ + Level1b: 2, + Level1c: 3, + }, + Embed0a: &Embed0a{ + Level1a: 5, + Level1b: 6, + }, + Embed0b: &Embed0b{ + Level1a: 8, + Level1b: 9, + Level1c: 10, + Level1d: 11, + Level1e: 12, + }, + Loop: Loop{ + Loop1: 13, + Loop2: 14, + }, + Embed0p: Embed0p{ + Point: image.Point{X: 15, Y: 16}, + }, + Embed0q: Embed0q{ + Point: Point{Z: 17}, + }, + embed: embed{ + Q: 18, + }, + } + b, err := json.Marshal(top) + if err != nil { + t.Fatal(err) + } + want := "{\"Level0\":1,\"Level1b\":2,\"Level1c\":3,\"Level1a\":5,\"LEVEL1B\":6,\"e\":{\"Level1a\":8,\"Level1b\":9,\"Level1c\":10,\"Level1d\":11,\"x\":12},\"Loop1\":13,\"Loop2\":14,\"X\":15,\"Y\":16,\"Z\":17,\"Q\":18}" + if string(b) != want { + t.Errorf("Wrong marshal result.\n got: %q\nwant: %q", b, want) + } +} + +func equalError(a, b error) bool { + if a == nil { + return b == nil + } + if b == nil { + return a == nil + } + return a.Error() == b.Error() +} + +func TestUnmarshal(t *testing.T) { + for i, tt := range unmarshalTests { + in := []byte(tt.in) + if tt.ptr == nil { + continue + } + + typ := reflect.TypeOf(tt.ptr) + if typ.Kind() != reflect.Ptr { + t.Errorf("#%d: unmarshalTest.ptr %T is not a pointer type", i, tt.ptr) + continue + } + typ = typ.Elem() + + // v = new(right-type) + v := reflect.New(typ) + + if !reflect.DeepEqual(tt.ptr, v.Interface()) { + // There's no reason for ptr to point to non-zero data, + // as we decode into new(right-type), so the data is + // discarded. + // This can easily mean tests that silently don't test + // what they should. To test decoding into existing + // data, see TestPrefilled. + t.Errorf("#%d: unmarshalTest.ptr %#v is not a pointer to a zero value", i, tt.ptr) + continue + } + + dec := json.NewDecoder(bytes.NewReader(in)) + if tt.useNumber { + dec.UseNumber() + } + if tt.disallowUnknownFields { + dec.DisallowUnknownFields() + } + if err := dec.Decode(v.Interface()); !equalError(err, tt.err) { + t.Errorf("#%d: %v, want %v", i, err, tt.err) + continue + } else if err != nil { + continue + } + if !reflect.DeepEqual(v.Elem().Interface(), tt.out) { + t.Errorf("#%d: mismatch\nhave: %#+v\nwant: %#+v", i, v.Elem().Interface(), tt.out) + data, _ := json.Marshal(v.Elem().Interface()) + println(string(data)) + data, _ = json.Marshal(tt.out) + println(string(data)) + continue + } + + // Check round trip also decodes correctly. + if tt.err == nil { + enc, err := json.Marshal(v.Interface()) + if err != nil { + t.Errorf("#%d: error re-marshaling: %v", i, err) + continue + } + if tt.golden && !bytes.Equal(enc, in) { + t.Errorf("#%d: remarshal mismatch:\nhave: %s\nwant: %s", i, enc, in) + } + vv := reflect.New(reflect.TypeOf(tt.ptr).Elem()) + dec = json.NewDecoder(bytes.NewReader(enc)) + if tt.useNumber { + dec.UseNumber() + } + if err := dec.Decode(vv.Interface()); err != nil { + t.Errorf("#%d: error re-unmarshaling %#q: %v", i, enc, err) + continue + } + if !reflect.DeepEqual(v.Elem().Interface(), vv.Elem().Interface()) { + t.Errorf("#%d: mismatch\nhave: %#+v\nwant: %#+v", i, v.Elem().Interface(), vv.Elem().Interface()) + t.Errorf(" In: %q", strings.Map(noSpace, string(in))) + t.Errorf("Marshal: %q", strings.Map(noSpace, string(enc))) + continue + } + } + } +} + +func TestUnmarshalMarshal(t *testing.T) { + initBig() + var v interface{} + if err := json.Unmarshal(jsonBig, &v); err != nil { + t.Fatalf("Unmarshal: %v", err) + } + b, err := json.Marshal(v) + if err != nil { + t.Fatalf("Marshal: %v", err) + } + if !bytes.Equal(jsonBig, b) { + t.Errorf("Marshal jsonBig") + diff(t, b, jsonBig) + return + } +} + +var numberTests = []struct { + in string + i int64 + intErr string + f float64 + floatErr string +}{ + {in: "-1.23e1", intErr: "strconv.ParseInt: parsing \"-1.23e1\": invalid syntax", f: -1.23e1}, + {in: "-12", i: -12, f: -12.0}, + {in: "1e1000", intErr: "strconv.ParseInt: parsing \"1e1000\": invalid syntax", floatErr: "strconv.ParseFloat: parsing \"1e1000\": value out of range"}, +} + +// Independent of Decode, basic coverage of the accessors in Number +func TestNumberAccessors(t *testing.T) { + for _, tt := range numberTests { + n := json.Number(tt.in) + if s := n.String(); s != tt.in { + t.Errorf("Number(%q).String() is %q", tt.in, s) + } + if i, err := n.Int64(); err == nil && tt.intErr == "" && i != tt.i { + t.Errorf("Number(%q).Int64() is %d", tt.in, i) + } else if (err == nil && tt.intErr != "") || (err != nil && err.Error() != tt.intErr) { + t.Errorf("Number(%q).Int64() wanted error %q but got: %v", tt.in, tt.intErr, err) + } + if f, err := n.Float64(); err == nil && tt.floatErr == "" && f != tt.f { + t.Errorf("Number(%q).Float64() is %g", tt.in, f) + } else if (err == nil && tt.floatErr != "") || (err != nil && err.Error() != tt.floatErr) { + t.Errorf("Number(%q).Float64() wanted error %q but got: %v", tt.in, tt.floatErr, err) + } + } +} + +func TestLargeByteSlice(t *testing.T) { + s0 := make([]byte, 2000) + for i := range s0 { + s0[i] = byte(i) + } + b, err := json.Marshal(s0) + if err != nil { + t.Fatalf("Marshal: %v", err) + } + var s1 []byte + if err := json.Unmarshal(b, &s1); err != nil { + t.Fatalf("Unmarshal: %v", err) + } + if !bytes.Equal(s0, s1) { + t.Errorf("Marshal large byte slice") + diff(t, s0, s1) + } +} + +type Xint struct { + X int +} + +func TestUnmarshalInterface(t *testing.T) { + var xint Xint + var i interface{} = &xint + if err := json.Unmarshal([]byte(`{"X":1}`), &i); err != nil { + t.Fatalf("Unmarshal: %v", err) + } + if xint.X != 1 { + t.Fatalf("Did not write to xint") + } +} + +func TestUnmarshalPtrPtr(t *testing.T) { + var xint Xint + pxint := &xint + if err := json.Unmarshal([]byte(`{"X":1}`), &pxint); err != nil { + t.Fatalf("Unmarshal: %v", err) + } + if xint.X != 1 { + t.Fatalf("Did not write to xint") + } +} + +func TestEscape(t *testing.T) { + const input = `"foobar"` + " [\u2028 \u2029]" + const expected = `"\"foobar\"\u003chtml\u003e [\u2028 \u2029]"` + b, err := json.Marshal(input) + if err != nil { + t.Fatalf("Marshal error: %v", err) + } + if s := string(b); s != expected { + t.Errorf("Encoding of [%s]:\n got [%s]\nwant [%s]", input, s, expected) + } +} + +// WrongString is a struct that's misusing the ,string modifier. +type WrongString struct { + Message string `json:"result,string"` +} + +type wrongStringTest struct { + in, err string +} + +var wrongStringTests = []wrongStringTest{ + {`{"result":"x"}`, `json: invalid use of ,string struct tag, trying to unmarshal "x" into string`}, + {`{"result":"foo"}`, `json: invalid use of ,string struct tag, trying to unmarshal "foo" into string`}, + {`{"result":"123"}`, `json: invalid use of ,string struct tag, trying to unmarshal "123" into string`}, + {`{"result":123}`, `json: invalid use of ,string struct tag, trying to unmarshal unquoted value into string`}, + {`{"result":"\""}`, `json: invalid use of ,string struct tag, trying to unmarshal "\"" into string`}, + {`{"result":"\"foo"}`, `json: invalid use of ,string struct tag, trying to unmarshal "\"foo" into string`}, +} + +// If people misuse the ,string modifier, the error message should be +// helpful, telling the user that they're doing it wrong. +func TestErrorMessageFromMisusedString(t *testing.T) { + for n, tt := range wrongStringTests { + r := strings.NewReader(tt.in) + var s WrongString + err := json.NewDecoder(r).Decode(&s) + got := fmt.Sprintf("%v", err) + if got != tt.err { + t.Errorf("%d. got err = %q, want %q", n, got, tt.err) + } + } +} + +func TestRefUnmarshal(t *testing.T) { + type S struct { + // Ref is defined in encode_test.go. + R0 Ref + R1 *Ref + R2 RefText + R3 *RefText + } + want := S{ + R0: 12, + R1: new(Ref), + R2: 13, + R3: new(RefText), + } + *want.R1 = 12 + *want.R3 = 13 + + var got S + if err := json.Unmarshal([]byte(`{"R0":"ref","R1":"ref","R2":"ref","R3":"ref"}`), &got); err != nil { + t.Fatalf("Unmarshal: %v", err) + } + if !reflect.DeepEqual(got, want) { + t.Errorf("got %+v, want %+v", got, want) + } +} + +// Test that the empty string doesn't panic decoding when ,string is specified +// Issue 3450 +func TestEmptyString(t *testing.T) { + type T2 struct { + Number1 int `json:",string"` + Number2 int `json:",string"` + } + data := `{"Number1":"1", "Number2":""}` + dec := json.NewDecoder(strings.NewReader(data)) + var t2 T2 + err := dec.Decode(&t2) + if err == nil { + t.Fatal("Decode: did not return error") + } + if t2.Number1 != 1 { + t.Fatal("Decode: did not set Number1") + } +} + +// Test that a null for ,string is not replaced with the previous quoted string (issue 7046). +// It should also not be an error (issue 2540, issue 8587). +func TestNullString(t *testing.T) { + type T struct { + A int `json:",string"` + B int `json:",string"` + C *int `json:",string"` + } + data := []byte(`{"A": "1", "B": null, "C": null}`) + var s T + s.B = 1 + s.C = new(int) + *s.C = 2 + err := json.Unmarshal(data, &s) + if err != nil { + t.Fatalf("Unmarshal: %v", err) + } + if s.B != 1 || s.C != nil { + t.Fatalf("after Unmarshal, s.B=%d, s.C=%p, want 1, nil", s.B, s.C) + } +} + +func intp(x int) *int { + p := new(int) + *p = x + return p +} + +func intpp(x *int) **int { + pp := new(*int) + *pp = x + return pp +} + +var interfaceSetTests = []struct { + pre interface{} + json string + post interface{} +}{ + {"foo", `"bar"`, "bar"}, + {"foo", `2`, 2.0}, + {"foo", `true`, true}, + {"foo", `null`, nil}, + + {nil, `null`, nil}, + {new(int), `null`, nil}, + {(*int)(nil), `null`, nil}, + {new(*int), `null`, new(*int)}, + {(**int)(nil), `null`, nil}, + {intp(1), `null`, nil}, + {intpp(nil), `null`, intpp(nil)}, + {intpp(intp(1)), `null`, intpp(nil)}, +} + +func TestInterfaceSet(t *testing.T) { + for _, tt := range interfaceSetTests { + b := struct{ X interface{} }{tt.pre} + blob := `{"X":` + tt.json + `}` + if err := json.Unmarshal([]byte(blob), &b); err != nil { + t.Errorf("Unmarshal %#q: %v", blob, err) + continue + } + if !reflect.DeepEqual(b.X, tt.post) { + t.Errorf("Unmarshal %#q into %#v: X=%#v, want %#v", blob, tt.pre, b.X, tt.post) + } + } +} + +// JSON null values should be ignored for primitives and string values instead of resulting in an error. +// Issue 2540 +func TestUnmarshalNulls(t *testing.T) { + // Unmarshal docs: + // The JSON null value unmarshals into an interface, map, pointer, or slice + // by setting that Go value to nil. Because null is often used in JSON to mean + // ``not present,'' unmarshaling a JSON null into any other Go type has no effect + // on the value and produces no error. + + jsonData := []byte(`{ + "Bool" : null, + "Int" : null, + "Int8" : null, + "Int16" : null, + "Int32" : null, + "Int64" : null, + "Uint" : null, + "Uint8" : null, + "Uint16" : null, + "Uint32" : null, + "Uint64" : null, + "Float32" : null, + "Float64" : null, + "String" : null, + "PBool": null, + "Map": null, + "Slice": null, + "Interface": null, + "PRaw": null, + "PTime": null, + "PBigInt": null, + "PText": null, + "PBuffer": null, + "PStruct": null, + "Raw": null, + "Time": null, + "BigInt": null, + "Text": null, + "Buffer": null, + "Struct": null + }`) + nulls := NullTest{ + Bool: true, + Int: 2, + Int8: 3, + Int16: 4, + Int32: 5, + Int64: 6, + Uint: 7, + Uint8: 8, + Uint16: 9, + Uint32: 10, + Uint64: 11, + Float32: 12.1, + Float64: 13.1, + String: "14", + PBool: new(bool), + Map: map[string]string{}, + Slice: []string{}, + Interface: new(MustNotUnmarshalJSON), + PRaw: new(json.RawMessage), + PTime: new(time.Time), + PBigInt: new(big.Int), + PText: new(MustNotUnmarshalText), + PStruct: new(struct{}), + PBuffer: new(bytes.Buffer), + Raw: json.RawMessage("123"), + Time: time.Unix(123456789, 0), + BigInt: *big.NewInt(123), + } + + before := nulls.Time.String() + + err := json.Unmarshal(jsonData, &nulls) + if err != nil { + t.Errorf("Unmarshal of null values failed: %v", err) + } + if !nulls.Bool || nulls.Int != 2 || nulls.Int8 != 3 || nulls.Int16 != 4 || nulls.Int32 != 5 || nulls.Int64 != 6 || + nulls.Uint != 7 || nulls.Uint8 != 8 || nulls.Uint16 != 9 || nulls.Uint32 != 10 || nulls.Uint64 != 11 || + nulls.Float32 != 12.1 || nulls.Float64 != 13.1 || nulls.String != "14" { + t.Errorf("Unmarshal of null values affected primitives") + } + + if nulls.PBool != nil { + t.Errorf("Unmarshal of null did not clear nulls.PBool") + } + if nulls.Map != nil { + t.Errorf("Unmarshal of null did not clear nulls.Map") + } + if nulls.Slice != nil { + t.Errorf("Unmarshal of null did not clear nulls.Slice") + } + if nulls.Interface != nil { + t.Errorf("Unmarshal of null did not clear nulls.Interface") + } + if nulls.PRaw != nil { + t.Errorf("Unmarshal of null did not clear nulls.PRaw") + } + if nulls.PTime != nil { + t.Errorf("Unmarshal of null did not clear nulls.PTime") + } + if nulls.PBigInt != nil { + t.Errorf("Unmarshal of null did not clear nulls.PBigInt") + } + if nulls.PText != nil { + t.Errorf("Unmarshal of null did not clear nulls.PText") + } + if nulls.PBuffer != nil { + t.Errorf("Unmarshal of null did not clear nulls.PBuffer") + } + if nulls.PStruct != nil { + t.Errorf("Unmarshal of null did not clear nulls.PStruct") + } + + if string(nulls.Raw) != "null" { + t.Errorf("Unmarshal of RawMessage null did not record null: %v", string(nulls.Raw)) + } + if nulls.Time.String() != before { + t.Errorf("Unmarshal of time.Time null set time to %v", nulls.Time.String()) + } + if nulls.BigInt.String() != "123" { + t.Errorf("Unmarshal of big.Int null set int to %v", nulls.BigInt.String()) + } +} + +func TestStringKind(t *testing.T) { + type stringKind string + + var m1, m2 map[stringKind]int + m1 = map[stringKind]int{ + "foo": 42, + } + + data, err := json.Marshal(m1) + if err != nil { + t.Errorf("Unexpected error marshaling: %v", err) + } + + err = json.Unmarshal(data, &m2) + if err != nil { + t.Errorf("Unexpected error unmarshaling: %v", err) + } + + if !reflect.DeepEqual(m1, m2) { + t.Error("Items should be equal after encoding and then decoding") + } +} + +// Custom types with []byte as underlying type could not be marshaled +// and then unmarshaled. +// Issue 8962. +func TestByteKind(t *testing.T) { + type byteKind []byte + + a := byteKind("hello") + + data, err := json.Marshal(a) + if err != nil { + t.Error(err) + } + var b byteKind + err = json.Unmarshal(data, &b) + if err != nil { + t.Fatal(err) + } + if !reflect.DeepEqual(a, b) { + t.Errorf("expected %v == %v", a, b) + } +} + +// The fix for issue 8962 introduced a regression. +// Issue 12921. +func TestSliceOfCustomByte(t *testing.T) { + type Uint8 uint8 + + a := []Uint8("hello") + + data, err := json.Marshal(a) + if err != nil { + t.Fatal(err) + } + var b []Uint8 + err = json.Unmarshal(data, &b) + if err != nil { + t.Fatal(err) + } + if !reflect.DeepEqual(a, b) { + t.Fatalf("expected %v == %v", a, b) + } +} + +var decodeTypeErrorTests = []struct { + dest interface{} + src string +}{ + {new(string), `{"user": "name"}`}, // issue 4628. + {new(error), `{}`}, // issue 4222 + {new(error), `[]`}, + {new(error), `""`}, + {new(error), `123`}, + {new(error), `true`}, +} + +func TestUnmarshalTypeError(t *testing.T) { + for _, item := range decodeTypeErrorTests { + err := json.Unmarshal([]byte(item.src), item.dest) + if _, ok := err.(*json.UnmarshalTypeError); !ok { + t.Errorf("expected type error for Unmarshal(%q, type %T): got %T", + item.src, item.dest, err) + } + } +} + +var unmarshalSyntaxTests = []string{ + "tru", + "fals", + "nul", + "123e", + `"hello`, + `[1,2,3`, + `{"key":1`, + `{"key":1,`, +} + +func TestUnmarshalSyntax(t *testing.T) { + var x interface{} + for _, src := range unmarshalSyntaxTests { + err := json.Unmarshal([]byte(src), &x) + if _, ok := err.(*json.SyntaxError); !ok { + t.Errorf("expected syntax error for Unmarshal(%q): got %T", src, err) + } + } +} + +// Test handling of unexported fields that should be ignored. +// Issue 4660 +type unexportedFields struct { + Name string + m map[string]interface{} `json:"-"` + m2 map[string]interface{} `json:"abcd"` + + s []int `json:"-"` +} + +func TestUnmarshalUnexported(t *testing.T) { + input := `{"Name": "Bob", "m": {"x": 123}, "m2": {"y": 456}, "abcd": {"z": 789}, "s": [2, 3]}` + want := &unexportedFields{Name: "Bob"} + + out := &unexportedFields{} + err := json.Unmarshal([]byte(input), out) + if err != nil { + t.Errorf("got error %v, expected nil", err) + } + if !reflect.DeepEqual(out, want) { + t.Errorf("got %q, want %q", out, want) + } +} + +// Time3339 is a time.Time which encodes to and from JSON +// as an RFC 3339 time in UTC. +type Time3339 time.Time + +func (t *Time3339) UnmarshalJSON(b []byte) error { + if len(b) < 2 || b[0] != '"' || b[len(b)-1] != '"' { + return fmt.Errorf("types: failed to unmarshal non-string value %q as an RFC 3339 time", b) + } + tm, err := time.Parse(time.RFC3339, string(b[1:len(b)-1])) + if err != nil { + return err + } + *t = Time3339(tm) + return nil +} + +func TestUnmarshalJSONLiteralError(t *testing.T) { + var t3 Time3339 + err := json.Unmarshal([]byte(`"0000-00-00T00:00:00Z"`), &t3) + if err == nil { + t.Fatalf("expected error; got time %v", time.Time(t3)) + } + if !strings.Contains(err.Error(), "range") { + t.Errorf("got err = %v; want out of range error", err) + } +} + +// Test that extra object elements in an array do not result in a +// "data changing underfoot" error. +// Issue 3717 +func TestSkipArrayObjects(t *testing.T) { + data := `[{}]` + var dest [0]interface{} + + err := json.Unmarshal([]byte(data), &dest) + if err != nil { + t.Errorf("got error %q, want nil", err) + } +} + +// Test semantics of pre-filled data, such as struct fields, map elements, +// slices, and arrays. +// Issues 4900 and 8837, among others. +func TestPrefilled(t *testing.T) { + // Values here change, cannot reuse table across runs. + var prefillTests = []struct { + in string + ptr interface{} + out interface{} + }{ + { + in: `{"X": 1, "Y": 2}`, + ptr: &XYZ{X: float32(3), Y: int16(4), Z: 1.5}, + out: &XYZ{X: float64(1), Y: float64(2), Z: 1.5}, + }, + { + in: `{"X": 1, "Y": 2}`, + ptr: &map[string]interface{}{"X": float32(3), "Y": int16(4), "Z": 1.5}, + out: &map[string]interface{}{"X": float64(1), "Y": float64(2), "Z": 1.5}, + }, + { + in: `[2]`, + ptr: &[]int{1}, + out: &[]int{2}, + }, + { + in: `[2, 3]`, + ptr: &[]int{1}, + out: &[]int{2, 3}, + }, + { + in: `[2, 3]`, + ptr: &[...]int{1}, + out: &[...]int{2}, + }, + { + in: `[3]`, + ptr: &[...]int{1, 2}, + out: &[...]int{3, 0}, + }, + } + + for _, tt := range prefillTests { + ptrstr := fmt.Sprintf("%v", tt.ptr) + err := json.Unmarshal([]byte(tt.in), tt.ptr) // tt.ptr edited here + if err != nil { + t.Errorf("Unmarshal: %v", err) + } + if !reflect.DeepEqual(tt.ptr, tt.out) { + t.Errorf("Unmarshal(%#q, %s): have %v, want %v", tt.in, ptrstr, tt.ptr, tt.out) + } + } +} + +var invalidUnmarshalTests = []struct { + v interface{} + want string +}{ + {nil, "json: Unmarshal(nil)"}, + {struct{}{}, "json: Unmarshal(non-pointer struct {})"}, + {(*int)(nil), "json: Unmarshal(nil *int)"}, +} + +func TestInvalidUnmarshal(t *testing.T) { + buf := []byte(`{"a":"1"}`) + for _, tt := range invalidUnmarshalTests { + err := json.Unmarshal(buf, tt.v) + if err == nil { + t.Errorf("Unmarshal expecting error, got nil") + continue + } + if got := err.Error(); got != tt.want { + t.Errorf("Unmarshal = %q; want %q", got, tt.want) + } + } +} + +var invalidUnmarshalTextTests = []struct { + v interface{} + want string +}{ + {nil, "json: Unmarshal(nil)"}, + {struct{}{}, "json: Unmarshal(non-pointer struct {})"}, + {(*int)(nil), "json: Unmarshal(nil *int)"}, + {new(net.IP), "json: cannot unmarshal number into Go value of type *net.IP"}, +} + +func TestInvalidUnmarshalText(t *testing.T) { + buf := []byte(`123`) + for _, tt := range invalidUnmarshalTextTests { + err := json.Unmarshal(buf, tt.v) + if err == nil { + t.Errorf("Unmarshal expecting error, got nil") + continue + } + if got := err.Error(); got != tt.want { + t.Errorf("Unmarshal = %q; want %q", got, tt.want) + } + } +} + +// Test that string option is ignored for invalid types. +// Issue 9812. +func TestInvalidStringOption(t *testing.T) { + num := 0 + item := struct { + T time.Time `json:",string"` + M map[string]string `json:",string"` + S []string `json:",string"` + A [1]string `json:",string"` + I interface{} `json:",string"` + P *int `json:",string"` + }{M: make(map[string]string), S: make([]string, 0), I: num, P: &num} + + data, err := json.Marshal(item) + if err != nil { + t.Fatalf("Marshal: %v", err) + } + + err = json.Unmarshal(data, &item) + if err != nil { + t.Fatalf("Unmarshal: %v", err) + } +} + +// Test unmarshal behavior with regards to embedded unexported structs. +// +// (Issue 21357) If the embedded struct is a pointer and is unallocated, +// this returns an error because unmarshal cannot set the field. +// +// (Issue 24152) If the embedded struct is given an explicit name, +// ensure that the normal unmarshal logic does not panic in reflect. +// +// (Issue 28145) If the embedded struct is given an explicit name and has +// exported methods, don't cause a panic trying to get its value. +func TestUnmarshalEmbeddedUnexported(t *testing.T) { + type ( + embed1 struct{ Q int } + embed2 struct{ Q int } + embed3 struct { + Q int64 `json:",string"` + } + S1 struct { + *embed1 + R int + } + S2 struct { + *embed1 + Q int + } + S3 struct { + embed1 + R int + } + S4 struct { + *embed1 + embed2 + } + S5 struct { + *embed3 + R int + } + S6 struct { + embed1 `json:"embed1"` + } + S7 struct { + embed1 `json:"embed1"` + embed2 + } + S8 struct { + embed1 `json:"embed1"` + embed2 `json:"embed2"` + Q int + } + S9 struct { + unexportedWithMethods `json:"embed"` + } + ) + + tests := []struct { + in string + ptr interface{} + out interface{} + err error + }{{ + // Error since we cannot set S1.embed1, but still able to set S1.R. + in: `{"R":2,"Q":1}`, + ptr: new(S1), + out: &S1{R: 2}, + err: fmt.Errorf("json: cannot set embedded pointer to unexported struct: json.embed1"), + }, { + // The top level Q field takes precedence. + in: `{"Q":1}`, + ptr: new(S2), + out: &S2{Q: 1}, + }, { + // No issue with non-pointer variant. + in: `{"R":2,"Q":1}`, + ptr: new(S3), + out: &S3{embed1: embed1{Q: 1}, R: 2}, + }, { + // No error since both embedded structs have field R, which annihilate each other. + // Thus, no attempt is made at setting S4.embed1. + in: `{"R":2}`, + ptr: new(S4), + out: new(S4), + }, { + // Error since we cannot set S5.embed1, but still able to set S5.R. + in: `{"R":2,"Q":1}`, + ptr: new(S5), + out: &S5{R: 2}, + err: fmt.Errorf("json: cannot set embedded pointer to unexported struct: json.embed3"), + }, { + // Issue 24152, ensure decodeState.indirect does not panic. + in: `{"embed1": {"Q": 1}}`, + ptr: new(S6), + out: &S6{embed1{1}}, + }, { + // Issue 24153, check that we can still set forwarded fields even in + // the presence of a name conflict. + // + // This relies on obscure behavior of reflect where it is possible + // to set a forwarded exported field on an unexported embedded struct + // even though there is a name conflict, even when it would have been + // impossible to do so according to Go visibility rules. + // Go forbids this because it is ambiguous whether S7.Q refers to + // S7.embed1.Q or S7.embed2.Q. Since embed1 and embed2 are unexported, + // it should be impossible for an external package to set either Q. + // + // It is probably okay for a future reflect change to break this. + in: `{"embed1": {"Q": 1}, "Q": 2}`, + ptr: new(S7), + out: &S7{embed1{1}, embed2{2}}, + }, { + // Issue 24153, similar to the S7 case. + in: `{"embed1": {"Q": 1}, "embed2": {"Q": 2}, "Q": 3}`, + ptr: new(S8), + out: &S8{embed1{1}, embed2{2}, 3}, + }, { + // Issue 228145, similar to the cases above. + in: `{"embed": {}}`, + ptr: new(S9), + out: &S9{}, + }} + + for i, tt := range tests { + err := json.Unmarshal([]byte(tt.in), tt.ptr) + if !equalError(err, tt.err) { + t.Errorf("#%d: %v, want %v", i, err, tt.err) + } + if !reflect.DeepEqual(tt.ptr, tt.out) { + t.Errorf("#%d: mismatch\ngot: %#+v\nwant: %#+v", i, tt.ptr, tt.out) + } + } +} + +func TestUnmarshalErrorAfterMultipleJSON(t *testing.T) { + tests := []struct { + in string + err error + }{{ + in: `1 false null :`, + err: json.NewSyntaxError("invalid character ':' looking for beginning of value", 14), + }, { + in: `1 [] [,]`, + err: json.NewSyntaxError("invalid character ',' looking for beginning of value", 7), + }, { + in: `1 [] [true:]`, + err: json.NewSyntaxError("invalid character ':' after array element", 11), + }, { + in: `1 {} {"x"=}`, + err: json.NewSyntaxError("invalid character '=' after object key", 14), + }, { + in: `falsetruenul#`, + err: json.NewSyntaxError("invalid character '#' in literal null (expecting 'l')", 13), + }} + for i, tt := range tests { + dec := json.NewDecoder(strings.NewReader(tt.in)) + var err error + for { + var v interface{} + if err = dec.Decode(&v); err != nil { + break + } + } + if !reflect.DeepEqual(err, tt.err) { + t.Errorf("#%d: got %#v, want %#v", i, err, tt.err) + } + } +} + +type unmarshalPanic struct{} + +func (unmarshalPanic) UnmarshalJSON([]byte) error { panic(0xdead) } + +func TestUnmarshalPanic(t *testing.T) { + defer func() { + if got := recover(); !reflect.DeepEqual(got, 0xdead) { + t.Errorf("panic() = (%T)(%v), want 0xdead", got, got) + } + }() + json.Unmarshal([]byte("{}"), &unmarshalPanic{}) + t.Fatalf("Unmarshal should have panicked") +} + +// The decoder used to hang if decoding into an interface pointing to its own address. +// See golang.org/issues/31740. +func TestUnmarshalRecursivePointer(t *testing.T) { + var v interface{} + v = &v + data := []byte(`{"a": "b"}`) + + if err := json.Unmarshal(data, v); err != nil { + t.Fatal(err) + } +} + +type textUnmarshalerString string + +func (m *textUnmarshalerString) UnmarshalText(text []byte) error { + *m = textUnmarshalerString(strings.ToLower(string(text))) + return nil +} + +// Test unmarshal to a map, where the map key is a user defined type. +// See golang.org/issues/34437. +func TestUnmarshalMapWithTextUnmarshalerStringKey(t *testing.T) { + var p map[textUnmarshalerString]string + if err := json.Unmarshal([]byte(`{"FOO": "1"}`), &p); err != nil { + t.Fatalf("Unmarshal unexpected error: %v", err) + } + + if _, ok := p["foo"]; !ok { + t.Errorf(`Key "foo" does not exist in map: %v`, p) + } +} + +func TestUnmarshalRescanLiteralMangledUnquote(t *testing.T) { + // See golang.org/issues/38105. + var p map[textUnmarshalerString]string + if err := json.Unmarshal([]byte(`{"开源":"12345开源"}`), &p); err != nil { + t.Fatalf("Unmarshal unexpected error: %v", err) + } + if _, ok := p["开源"]; !ok { + t.Errorf(`Key "开源" does not exist in map: %v`, p) + } + + // See golang.org/issues/38126. + type T struct { + F1 string `json:"F1,string"` + } + t1 := T{"aaa\tbbb"} + + b, err := json.Marshal(t1) + if err != nil { + t.Fatalf("Marshal unexpected error: %v", err) + } + var t2 T + if err := json.Unmarshal(b, &t2); err != nil { + t.Fatalf("Unmarshal unexpected error: %v", err) + } + if t1 != t2 { + t.Errorf("Marshal and Unmarshal roundtrip mismatch: want %q got %q", t1, t2) + } + + // See golang.org/issues/39555. + input := map[textUnmarshalerString]string{"FOO": "", `"`: ""} + + encoded, err := json.Marshal(input) + if err != nil { + t.Fatalf("Marshal unexpected error: %v", err) + } + var got map[textUnmarshalerString]string + if err := json.Unmarshal(encoded, &got); err != nil { + t.Fatalf("Unmarshal unexpected error: %v", err) + } + want := map[textUnmarshalerString]string{"foo": "", `"`: ""} + if !reflect.DeepEqual(want, got) { + t.Fatalf("Unexpected roundtrip result:\nwant: %q\ngot: %q", want, got) + } +} + +func TestUnmarshalMaxDepth(t *testing.T) { + testcases := []struct { + name string + data string + errMaxDepth bool + }{ + { + name: "ArrayUnderMaxNestingDepth", + data: `{"a":` + strings.Repeat(`[`, 10000-1) + strings.Repeat(`]`, 10000-1) + `}`, + errMaxDepth: false, + }, + { + name: "ArrayOverMaxNestingDepth", + data: `{"a":` + strings.Repeat(`[`, 10000) + strings.Repeat(`]`, 10000) + `}`, + errMaxDepth: true, + }, + { + name: "ArrayOverStackDepth", + data: `{"a":` + strings.Repeat(`[`, 3000000) + strings.Repeat(`]`, 3000000) + `}`, + errMaxDepth: true, + }, + { + name: "ObjectUnderMaxNestingDepth", + data: `{"a":` + strings.Repeat(`{"a":`, 10000-1) + `0` + strings.Repeat(`}`, 10000-1) + `}`, + errMaxDepth: false, + }, + { + name: "ObjectOverMaxNestingDepth", + data: `{"a":` + strings.Repeat(`{"a":`, 10000) + `0` + strings.Repeat(`}`, 10000) + `}`, + errMaxDepth: true, + }, + { + name: "ObjectOverStackDepth", + data: `{"a":` + strings.Repeat(`{"a":`, 3000000) + `0` + strings.Repeat(`}`, 3000000) + `}`, + errMaxDepth: true, + }, + } + + targets := []struct { + name string + newValue func() interface{} + }{ + { + name: "unstructured", + newValue: func() interface{} { + var v interface{} + return &v + }, + }, + { + name: "typed named field", + newValue: func() interface{} { + v := struct { + A interface{} `json:"a"` + }{} + return &v + }, + }, + { + name: "typed missing field", + newValue: func() interface{} { + v := struct { + B interface{} `json:"b"` + }{} + return &v + }, + }, + { + name: "custom unmarshaler", + newValue: func() interface{} { + v := unmarshaler{} + return &v + }, + }, + } + + for _, tc := range testcases { + for _, target := range targets { + t.Run(target.name+"-"+tc.name, func(t *testing.T) { + err := json.Unmarshal([]byte(tc.data), target.newValue()) + if !tc.errMaxDepth { + if err != nil { + t.Errorf("unexpected error: %v", err) + } + } else { + if err == nil { + t.Errorf("expected error containing 'exceeded max depth', got none") + } else if !strings.Contains(err.Error(), "exceeded max depth") { + t.Errorf("expected error containing 'exceeded max depth', got: %v", err) + } + } + }) + } + } +} +*/ diff --git a/encode_compile.go b/encode_compile.go index 798119f..460e37f 100644 --- a/encode_compile.go +++ b/encode_compile.go @@ -481,8 +481,39 @@ func (e *Encoder) typeToHeaderType(op opType) opType { return opStructFieldHead } -func (e *Encoder) typeToFieldType(op opType) opType { - switch op { +func (e *Encoder) typeToFieldType(code *opcode) opType { + switch code.op { + case opPtr: + switch code.next.op { + case opInt: + return opStructFieldPtrInt + case opInt8: + return opStructFieldPtrInt8 + case opInt16: + return opStructFieldPtrInt16 + case opInt32: + return opStructFieldPtrInt32 + case opInt64: + return opStructFieldPtrInt64 + case opUint: + return opStructFieldPtrUint + case opUint8: + return opStructFieldPtrUint8 + case opUint16: + return opStructFieldPtrUint16 + case opUint32: + return opStructFieldPtrUint32 + case opUint64: + return opStructFieldPtrUint64 + case opFloat32: + return opStructFieldPtrFloat32 + case opFloat64: + return opStructFieldPtrFloat64 + case opString: + return opStructFieldPtrString + case opBool: + return opStructFieldPtrBool + } case opInt: return opStructFieldInt case opInt8: @@ -553,8 +584,8 @@ func (e *Encoder) optimizeStructHeader(op opType, tag *structTag, withIndent boo return headType } -func (e *Encoder) optimizeStructField(op opType, tag *structTag, withIndent bool) opType { - fieldType := e.typeToFieldType(op) +func (e *Encoder) optimizeStructField(code *opcode, tag *structTag, withIndent bool) opType { + fieldType := e.typeToFieldType(code) switch { case tag.isOmitEmpty: fieldType = fieldType.fieldToOmitEmptyField() @@ -627,7 +658,7 @@ func (e *Encoder) structHeader(ctx *encodeCompileContext, fieldCode *opcode, val func (e *Encoder) structField(ctx *encodeCompileContext, fieldCode *opcode, valueCode *opcode, tag *structTag) *opcode { code := (*opcode)(unsafe.Pointer(fieldCode)) - op := e.optimizeStructField(valueCode.op, tag, ctx.withIndent) + op := e.optimizeStructField(valueCode, tag, ctx.withIndent) fieldCode.op = op switch op { case opStructField, diff --git a/encode_optype.go b/encode_optype.go index 0a830c8..ca3ad3b 100644 --- a/encode_optype.go +++ b/encode_optype.go @@ -364,438 +364,482 @@ const ( opStructFieldStruct opType = 341 opStructFieldMarshalJSON opType = 342 opStructFieldMarshalText opType = 343 - opStructFieldOmitEmptyInt opType = 344 - opStructFieldOmitEmptyInt8 opType = 345 - opStructFieldOmitEmptyInt16 opType = 346 - opStructFieldOmitEmptyInt32 opType = 347 - opStructFieldOmitEmptyInt64 opType = 348 - opStructFieldOmitEmptyUint opType = 349 - opStructFieldOmitEmptyUint8 opType = 350 - opStructFieldOmitEmptyUint16 opType = 351 - opStructFieldOmitEmptyUint32 opType = 352 - opStructFieldOmitEmptyUint64 opType = 353 - opStructFieldOmitEmptyFloat32 opType = 354 - opStructFieldOmitEmptyFloat64 opType = 355 - opStructFieldOmitEmptyBool opType = 356 - opStructFieldOmitEmptyString opType = 357 - opStructFieldOmitEmptyBytes opType = 358 - opStructFieldOmitEmptyArray opType = 359 - opStructFieldOmitEmptyMap opType = 360 - opStructFieldOmitEmptyMapLoad opType = 361 - opStructFieldOmitEmptySlice opType = 362 - opStructFieldOmitEmptyStruct opType = 363 - opStructFieldOmitEmptyMarshalJSON opType = 364 - opStructFieldOmitEmptyMarshalText opType = 365 - opStructFieldStringTagInt opType = 366 - opStructFieldStringTagInt8 opType = 367 - opStructFieldStringTagInt16 opType = 368 - opStructFieldStringTagInt32 opType = 369 - opStructFieldStringTagInt64 opType = 370 - opStructFieldStringTagUint opType = 371 - opStructFieldStringTagUint8 opType = 372 - opStructFieldStringTagUint16 opType = 373 - opStructFieldStringTagUint32 opType = 374 - opStructFieldStringTagUint64 opType = 375 - opStructFieldStringTagFloat32 opType = 376 - opStructFieldStringTagFloat64 opType = 377 - opStructFieldStringTagBool opType = 378 - opStructFieldStringTagString opType = 379 - opStructFieldStringTagBytes opType = 380 - opStructFieldStringTagArray opType = 381 - opStructFieldStringTagMap opType = 382 - opStructFieldStringTagMapLoad opType = 383 - opStructFieldStringTagSlice opType = 384 - opStructFieldStringTagStruct opType = 385 - opStructFieldStringTagMarshalJSON opType = 386 - opStructFieldStringTagMarshalText opType = 387 - opEndIndent opType = 388 - opInterfaceIndent opType = 389 - opInterfaceEndIndent opType = 390 - opPtrIndent opType = 391 - opSliceHeadIndent opType = 392 - opRootSliceHeadIndent opType = 393 - opSliceElemIndent opType = 394 - opRootSliceElemIndent opType = 395 - opSliceEndIndent opType = 396 - opArrayHeadIndent opType = 397 - opArrayElemIndent opType = 398 - opArrayEndIndent opType = 399 - opMapHeadIndent opType = 400 - opMapHeadLoadIndent opType = 401 - opMapKeyIndent opType = 402 - opMapValueIndent opType = 403 - opMapEndIndent opType = 404 - opStructFieldHeadIndent opType = 405 - opStructFieldHeadOmitEmptyIndent opType = 406 - opStructFieldHeadStringTagIndent opType = 407 - opStructFieldAnonymousHeadIndent opType = 408 - opStructFieldAnonymousHeadOmitEmptyIndent opType = 409 - opStructFieldPtrAnonymousHeadOmitEmptyIndent opType = 410 - opStructFieldAnonymousHeadStringTagIndent opType = 411 - opStructFieldPtrAnonymousHeadStringTagIndent opType = 412 - opStructFieldPtrHeadIndent opType = 413 - opStructFieldPtrHeadOmitEmptyIndent opType = 414 - opStructFieldPtrHeadStringTagIndent opType = 415 - opStructFieldPtrAnonymousHeadIndent opType = 416 - opStructFieldIndent opType = 417 - opStructFieldOmitEmptyIndent opType = 418 - opStructFieldStringTagIndent opType = 419 - opStructFieldRecursiveIndent opType = 420 - opStructFieldRecursiveEndIndent opType = 421 - opStructEndIndent opType = 422 - opStructAnonymousEndIndent opType = 423 - opIntIndent opType = 424 - opInt8Indent opType = 425 - opInt16Indent opType = 426 - opInt32Indent opType = 427 - opInt64Indent opType = 428 - opUintIndent opType = 429 - opUint8Indent opType = 430 - opUint16Indent opType = 431 - opUint32Indent opType = 432 - opUint64Indent opType = 433 - opFloat32Indent opType = 434 - opFloat64Indent opType = 435 - opBoolIndent opType = 436 - opStringIndent opType = 437 - opBytesIndent opType = 438 - opArrayIndent opType = 439 - opMapIndent opType = 440 - opMapLoadIndent opType = 441 - opSliceIndent opType = 442 - opStructIndent opType = 443 - opMarshalJSONIndent opType = 444 - opMarshalTextIndent opType = 445 - opStructFieldHeadIntIndent opType = 446 - opStructFieldHeadInt8Indent opType = 447 - opStructFieldHeadInt16Indent opType = 448 - opStructFieldHeadInt32Indent opType = 449 - opStructFieldHeadInt64Indent opType = 450 - opStructFieldHeadUintIndent opType = 451 - opStructFieldHeadUint8Indent opType = 452 - opStructFieldHeadUint16Indent opType = 453 - opStructFieldHeadUint32Indent opType = 454 - opStructFieldHeadUint64Indent opType = 455 - opStructFieldHeadFloat32Indent opType = 456 - opStructFieldHeadFloat64Indent opType = 457 - opStructFieldHeadBoolIndent opType = 458 - opStructFieldHeadStringIndent opType = 459 - opStructFieldHeadBytesIndent opType = 460 - opStructFieldHeadArrayIndent opType = 461 - opStructFieldHeadMapIndent opType = 462 - opStructFieldHeadMapLoadIndent opType = 463 - opStructFieldHeadSliceIndent opType = 464 - opStructFieldHeadStructIndent opType = 465 - opStructFieldHeadMarshalJSONIndent opType = 466 - opStructFieldHeadMarshalTextIndent opType = 467 - opStructFieldHeadOmitEmptyIntIndent opType = 468 - opStructFieldHeadOmitEmptyInt8Indent opType = 469 - opStructFieldHeadOmitEmptyInt16Indent opType = 470 - opStructFieldHeadOmitEmptyInt32Indent opType = 471 - opStructFieldHeadOmitEmptyInt64Indent opType = 472 - opStructFieldHeadOmitEmptyUintIndent opType = 473 - opStructFieldHeadOmitEmptyUint8Indent opType = 474 - opStructFieldHeadOmitEmptyUint16Indent opType = 475 - opStructFieldHeadOmitEmptyUint32Indent opType = 476 - opStructFieldHeadOmitEmptyUint64Indent opType = 477 - opStructFieldHeadOmitEmptyFloat32Indent opType = 478 - opStructFieldHeadOmitEmptyFloat64Indent opType = 479 - opStructFieldHeadOmitEmptyBoolIndent opType = 480 - opStructFieldHeadOmitEmptyStringIndent opType = 481 - opStructFieldHeadOmitEmptyBytesIndent opType = 482 - opStructFieldHeadOmitEmptyArrayIndent opType = 483 - opStructFieldHeadOmitEmptyMapIndent opType = 484 - opStructFieldHeadOmitEmptyMapLoadIndent opType = 485 - opStructFieldHeadOmitEmptySliceIndent opType = 486 - opStructFieldHeadOmitEmptyStructIndent opType = 487 - opStructFieldHeadOmitEmptyMarshalJSONIndent opType = 488 - opStructFieldHeadOmitEmptyMarshalTextIndent opType = 489 - opStructFieldHeadStringTagIntIndent opType = 490 - opStructFieldHeadStringTagInt8Indent opType = 491 - opStructFieldHeadStringTagInt16Indent opType = 492 - opStructFieldHeadStringTagInt32Indent opType = 493 - opStructFieldHeadStringTagInt64Indent opType = 494 - opStructFieldHeadStringTagUintIndent opType = 495 - opStructFieldHeadStringTagUint8Indent opType = 496 - opStructFieldHeadStringTagUint16Indent opType = 497 - opStructFieldHeadStringTagUint32Indent opType = 498 - opStructFieldHeadStringTagUint64Indent opType = 499 - opStructFieldHeadStringTagFloat32Indent opType = 500 - opStructFieldHeadStringTagFloat64Indent opType = 501 - opStructFieldHeadStringTagBoolIndent opType = 502 - opStructFieldHeadStringTagStringIndent opType = 503 - opStructFieldHeadStringTagBytesIndent opType = 504 - opStructFieldHeadStringTagArrayIndent opType = 505 - opStructFieldHeadStringTagMapIndent opType = 506 - opStructFieldHeadStringTagMapLoadIndent opType = 507 - opStructFieldHeadStringTagSliceIndent opType = 508 - opStructFieldHeadStringTagStructIndent opType = 509 - opStructFieldHeadStringTagMarshalJSONIndent opType = 510 - opStructFieldHeadStringTagMarshalTextIndent opType = 511 - opStructFieldAnonymousHeadIntIndent opType = 512 - opStructFieldAnonymousHeadInt8Indent opType = 513 - opStructFieldAnonymousHeadInt16Indent opType = 514 - opStructFieldAnonymousHeadInt32Indent opType = 515 - opStructFieldAnonymousHeadInt64Indent opType = 516 - opStructFieldAnonymousHeadUintIndent opType = 517 - opStructFieldAnonymousHeadUint8Indent opType = 518 - opStructFieldAnonymousHeadUint16Indent opType = 519 - opStructFieldAnonymousHeadUint32Indent opType = 520 - opStructFieldAnonymousHeadUint64Indent opType = 521 - opStructFieldAnonymousHeadFloat32Indent opType = 522 - opStructFieldAnonymousHeadFloat64Indent opType = 523 - opStructFieldAnonymousHeadBoolIndent opType = 524 - opStructFieldAnonymousHeadStringIndent opType = 525 - opStructFieldAnonymousHeadBytesIndent opType = 526 - opStructFieldAnonymousHeadArrayIndent opType = 527 - opStructFieldAnonymousHeadMapIndent opType = 528 - opStructFieldAnonymousHeadMapLoadIndent opType = 529 - opStructFieldAnonymousHeadSliceIndent opType = 530 - opStructFieldAnonymousHeadStructIndent opType = 531 - opStructFieldAnonymousHeadMarshalJSONIndent opType = 532 - opStructFieldAnonymousHeadMarshalTextIndent opType = 533 - opStructFieldAnonymousHeadOmitEmptyIntIndent opType = 534 - opStructFieldAnonymousHeadOmitEmptyInt8Indent opType = 535 - opStructFieldAnonymousHeadOmitEmptyInt16Indent opType = 536 - opStructFieldAnonymousHeadOmitEmptyInt32Indent opType = 537 - opStructFieldAnonymousHeadOmitEmptyInt64Indent opType = 538 - opStructFieldAnonymousHeadOmitEmptyUintIndent opType = 539 - opStructFieldAnonymousHeadOmitEmptyUint8Indent opType = 540 - opStructFieldAnonymousHeadOmitEmptyUint16Indent opType = 541 - opStructFieldAnonymousHeadOmitEmptyUint32Indent opType = 542 - opStructFieldAnonymousHeadOmitEmptyUint64Indent opType = 543 - opStructFieldAnonymousHeadOmitEmptyFloat32Indent opType = 544 - opStructFieldAnonymousHeadOmitEmptyFloat64Indent opType = 545 - opStructFieldAnonymousHeadOmitEmptyBoolIndent opType = 546 - opStructFieldAnonymousHeadOmitEmptyStringIndent opType = 547 - opStructFieldAnonymousHeadOmitEmptyBytesIndent opType = 548 - opStructFieldAnonymousHeadOmitEmptyArrayIndent opType = 549 - opStructFieldAnonymousHeadOmitEmptyMapIndent opType = 550 - opStructFieldAnonymousHeadOmitEmptyMapLoadIndent opType = 551 - opStructFieldAnonymousHeadOmitEmptySliceIndent opType = 552 - opStructFieldAnonymousHeadOmitEmptyStructIndent opType = 553 - opStructFieldAnonymousHeadOmitEmptyMarshalJSONIndent opType = 554 - opStructFieldAnonymousHeadOmitEmptyMarshalTextIndent opType = 555 - opStructFieldAnonymousHeadStringTagIntIndent opType = 556 - opStructFieldAnonymousHeadStringTagInt8Indent opType = 557 - opStructFieldAnonymousHeadStringTagInt16Indent opType = 558 - opStructFieldAnonymousHeadStringTagInt32Indent opType = 559 - opStructFieldAnonymousHeadStringTagInt64Indent opType = 560 - opStructFieldAnonymousHeadStringTagUintIndent opType = 561 - opStructFieldAnonymousHeadStringTagUint8Indent opType = 562 - opStructFieldAnonymousHeadStringTagUint16Indent opType = 563 - opStructFieldAnonymousHeadStringTagUint32Indent opType = 564 - opStructFieldAnonymousHeadStringTagUint64Indent opType = 565 - opStructFieldAnonymousHeadStringTagFloat32Indent opType = 566 - opStructFieldAnonymousHeadStringTagFloat64Indent opType = 567 - opStructFieldAnonymousHeadStringTagBoolIndent opType = 568 - opStructFieldAnonymousHeadStringTagStringIndent opType = 569 - opStructFieldAnonymousHeadStringTagBytesIndent opType = 570 - opStructFieldAnonymousHeadStringTagArrayIndent opType = 571 - opStructFieldAnonymousHeadStringTagMapIndent opType = 572 - opStructFieldAnonymousHeadStringTagMapLoadIndent opType = 573 - opStructFieldAnonymousHeadStringTagSliceIndent opType = 574 - opStructFieldAnonymousHeadStringTagStructIndent opType = 575 - opStructFieldAnonymousHeadStringTagMarshalJSONIndent opType = 576 - opStructFieldAnonymousHeadStringTagMarshalTextIndent opType = 577 - opStructFieldPtrHeadIntIndent opType = 578 - opStructFieldPtrHeadInt8Indent opType = 579 - opStructFieldPtrHeadInt16Indent opType = 580 - opStructFieldPtrHeadInt32Indent opType = 581 - opStructFieldPtrHeadInt64Indent opType = 582 - opStructFieldPtrHeadUintIndent opType = 583 - opStructFieldPtrHeadUint8Indent opType = 584 - opStructFieldPtrHeadUint16Indent opType = 585 - opStructFieldPtrHeadUint32Indent opType = 586 - opStructFieldPtrHeadUint64Indent opType = 587 - opStructFieldPtrHeadFloat32Indent opType = 588 - opStructFieldPtrHeadFloat64Indent opType = 589 - opStructFieldPtrHeadBoolIndent opType = 590 - opStructFieldPtrHeadStringIndent opType = 591 - opStructFieldPtrHeadBytesIndent opType = 592 - opStructFieldPtrHeadArrayIndent opType = 593 - opStructFieldPtrHeadMapIndent opType = 594 - opStructFieldPtrHeadMapLoadIndent opType = 595 - opStructFieldPtrHeadSliceIndent opType = 596 - opStructFieldPtrHeadStructIndent opType = 597 - opStructFieldPtrHeadMarshalJSONIndent opType = 598 - opStructFieldPtrHeadMarshalTextIndent opType = 599 - opStructFieldPtrHeadOmitEmptyIntIndent opType = 600 - opStructFieldPtrHeadOmitEmptyInt8Indent opType = 601 - opStructFieldPtrHeadOmitEmptyInt16Indent opType = 602 - opStructFieldPtrHeadOmitEmptyInt32Indent opType = 603 - opStructFieldPtrHeadOmitEmptyInt64Indent opType = 604 - opStructFieldPtrHeadOmitEmptyUintIndent opType = 605 - opStructFieldPtrHeadOmitEmptyUint8Indent opType = 606 - opStructFieldPtrHeadOmitEmptyUint16Indent opType = 607 - opStructFieldPtrHeadOmitEmptyUint32Indent opType = 608 - opStructFieldPtrHeadOmitEmptyUint64Indent opType = 609 - opStructFieldPtrHeadOmitEmptyFloat32Indent opType = 610 - opStructFieldPtrHeadOmitEmptyFloat64Indent opType = 611 - opStructFieldPtrHeadOmitEmptyBoolIndent opType = 612 - opStructFieldPtrHeadOmitEmptyStringIndent opType = 613 - opStructFieldPtrHeadOmitEmptyBytesIndent opType = 614 - opStructFieldPtrHeadOmitEmptyArrayIndent opType = 615 - opStructFieldPtrHeadOmitEmptyMapIndent opType = 616 - opStructFieldPtrHeadOmitEmptyMapLoadIndent opType = 617 - opStructFieldPtrHeadOmitEmptySliceIndent opType = 618 - opStructFieldPtrHeadOmitEmptyStructIndent opType = 619 - opStructFieldPtrHeadOmitEmptyMarshalJSONIndent opType = 620 - opStructFieldPtrHeadOmitEmptyMarshalTextIndent opType = 621 - opStructFieldPtrHeadStringTagIntIndent opType = 622 - opStructFieldPtrHeadStringTagInt8Indent opType = 623 - opStructFieldPtrHeadStringTagInt16Indent opType = 624 - opStructFieldPtrHeadStringTagInt32Indent opType = 625 - opStructFieldPtrHeadStringTagInt64Indent opType = 626 - opStructFieldPtrHeadStringTagUintIndent opType = 627 - opStructFieldPtrHeadStringTagUint8Indent opType = 628 - opStructFieldPtrHeadStringTagUint16Indent opType = 629 - opStructFieldPtrHeadStringTagUint32Indent opType = 630 - opStructFieldPtrHeadStringTagUint64Indent opType = 631 - opStructFieldPtrHeadStringTagFloat32Indent opType = 632 - opStructFieldPtrHeadStringTagFloat64Indent opType = 633 - opStructFieldPtrHeadStringTagBoolIndent opType = 634 - opStructFieldPtrHeadStringTagStringIndent opType = 635 - opStructFieldPtrHeadStringTagBytesIndent opType = 636 - opStructFieldPtrHeadStringTagArrayIndent opType = 637 - opStructFieldPtrHeadStringTagMapIndent opType = 638 - opStructFieldPtrHeadStringTagMapLoadIndent opType = 639 - opStructFieldPtrHeadStringTagSliceIndent opType = 640 - opStructFieldPtrHeadStringTagStructIndent opType = 641 - opStructFieldPtrHeadStringTagMarshalJSONIndent opType = 642 - opStructFieldPtrHeadStringTagMarshalTextIndent opType = 643 - opStructFieldPtrAnonymousHeadIntIndent opType = 644 - opStructFieldPtrAnonymousHeadInt8Indent opType = 645 - opStructFieldPtrAnonymousHeadInt16Indent opType = 646 - opStructFieldPtrAnonymousHeadInt32Indent opType = 647 - opStructFieldPtrAnonymousHeadInt64Indent opType = 648 - opStructFieldPtrAnonymousHeadUintIndent opType = 649 - opStructFieldPtrAnonymousHeadUint8Indent opType = 650 - opStructFieldPtrAnonymousHeadUint16Indent opType = 651 - opStructFieldPtrAnonymousHeadUint32Indent opType = 652 - opStructFieldPtrAnonymousHeadUint64Indent opType = 653 - opStructFieldPtrAnonymousHeadFloat32Indent opType = 654 - opStructFieldPtrAnonymousHeadFloat64Indent opType = 655 - opStructFieldPtrAnonymousHeadBoolIndent opType = 656 - opStructFieldPtrAnonymousHeadStringIndent opType = 657 - opStructFieldPtrAnonymousHeadBytesIndent opType = 658 - opStructFieldPtrAnonymousHeadArrayIndent opType = 659 - opStructFieldPtrAnonymousHeadMapIndent opType = 660 - opStructFieldPtrAnonymousHeadMapLoadIndent opType = 661 - opStructFieldPtrAnonymousHeadSliceIndent opType = 662 - opStructFieldPtrAnonymousHeadStructIndent opType = 663 - opStructFieldPtrAnonymousHeadMarshalJSONIndent opType = 664 - opStructFieldPtrAnonymousHeadMarshalTextIndent opType = 665 - opStructFieldPtrAnonymousHeadOmitEmptyIntIndent opType = 666 - opStructFieldPtrAnonymousHeadOmitEmptyInt8Indent opType = 667 - opStructFieldPtrAnonymousHeadOmitEmptyInt16Indent opType = 668 - opStructFieldPtrAnonymousHeadOmitEmptyInt32Indent opType = 669 - opStructFieldPtrAnonymousHeadOmitEmptyInt64Indent opType = 670 - opStructFieldPtrAnonymousHeadOmitEmptyUintIndent opType = 671 - opStructFieldPtrAnonymousHeadOmitEmptyUint8Indent opType = 672 - opStructFieldPtrAnonymousHeadOmitEmptyUint16Indent opType = 673 - opStructFieldPtrAnonymousHeadOmitEmptyUint32Indent opType = 674 - opStructFieldPtrAnonymousHeadOmitEmptyUint64Indent opType = 675 - opStructFieldPtrAnonymousHeadOmitEmptyFloat32Indent opType = 676 - opStructFieldPtrAnonymousHeadOmitEmptyFloat64Indent opType = 677 - opStructFieldPtrAnonymousHeadOmitEmptyBoolIndent opType = 678 - opStructFieldPtrAnonymousHeadOmitEmptyStringIndent opType = 679 - opStructFieldPtrAnonymousHeadOmitEmptyBytesIndent opType = 680 - opStructFieldPtrAnonymousHeadOmitEmptyArrayIndent opType = 681 - opStructFieldPtrAnonymousHeadOmitEmptyMapIndent opType = 682 - opStructFieldPtrAnonymousHeadOmitEmptyMapLoadIndent opType = 683 - opStructFieldPtrAnonymousHeadOmitEmptySliceIndent opType = 684 - opStructFieldPtrAnonymousHeadOmitEmptyStructIndent opType = 685 - opStructFieldPtrAnonymousHeadOmitEmptyMarshalJSONIndent opType = 686 - opStructFieldPtrAnonymousHeadOmitEmptyMarshalTextIndent opType = 687 - opStructFieldPtrAnonymousHeadStringTagIntIndent opType = 688 - opStructFieldPtrAnonymousHeadStringTagInt8Indent opType = 689 - opStructFieldPtrAnonymousHeadStringTagInt16Indent opType = 690 - opStructFieldPtrAnonymousHeadStringTagInt32Indent opType = 691 - opStructFieldPtrAnonymousHeadStringTagInt64Indent opType = 692 - opStructFieldPtrAnonymousHeadStringTagUintIndent opType = 693 - opStructFieldPtrAnonymousHeadStringTagUint8Indent opType = 694 - opStructFieldPtrAnonymousHeadStringTagUint16Indent opType = 695 - opStructFieldPtrAnonymousHeadStringTagUint32Indent opType = 696 - opStructFieldPtrAnonymousHeadStringTagUint64Indent opType = 697 - opStructFieldPtrAnonymousHeadStringTagFloat32Indent opType = 698 - opStructFieldPtrAnonymousHeadStringTagFloat64Indent opType = 699 - opStructFieldPtrAnonymousHeadStringTagBoolIndent opType = 700 - opStructFieldPtrAnonymousHeadStringTagStringIndent opType = 701 - opStructFieldPtrAnonymousHeadStringTagBytesIndent opType = 702 - opStructFieldPtrAnonymousHeadStringTagArrayIndent opType = 703 - opStructFieldPtrAnonymousHeadStringTagMapIndent opType = 704 - opStructFieldPtrAnonymousHeadStringTagMapLoadIndent opType = 705 - opStructFieldPtrAnonymousHeadStringTagSliceIndent opType = 706 - opStructFieldPtrAnonymousHeadStringTagStructIndent opType = 707 - opStructFieldPtrAnonymousHeadStringTagMarshalJSONIndent opType = 708 - opStructFieldPtrAnonymousHeadStringTagMarshalTextIndent opType = 709 - opStructFieldIntIndent opType = 710 - opStructFieldInt8Indent opType = 711 - opStructFieldInt16Indent opType = 712 - opStructFieldInt32Indent opType = 713 - opStructFieldInt64Indent opType = 714 - opStructFieldUintIndent opType = 715 - opStructFieldUint8Indent opType = 716 - opStructFieldUint16Indent opType = 717 - opStructFieldUint32Indent opType = 718 - opStructFieldUint64Indent opType = 719 - opStructFieldFloat32Indent opType = 720 - opStructFieldFloat64Indent opType = 721 - opStructFieldBoolIndent opType = 722 - opStructFieldStringIndent opType = 723 - opStructFieldBytesIndent opType = 724 - opStructFieldArrayIndent opType = 725 - opStructFieldMapIndent opType = 726 - opStructFieldMapLoadIndent opType = 727 - opStructFieldSliceIndent opType = 728 - opStructFieldStructIndent opType = 729 - opStructFieldMarshalJSONIndent opType = 730 - opStructFieldMarshalTextIndent opType = 731 - opStructFieldOmitEmptyIntIndent opType = 732 - opStructFieldOmitEmptyInt8Indent opType = 733 - opStructFieldOmitEmptyInt16Indent opType = 734 - opStructFieldOmitEmptyInt32Indent opType = 735 - opStructFieldOmitEmptyInt64Indent opType = 736 - opStructFieldOmitEmptyUintIndent opType = 737 - opStructFieldOmitEmptyUint8Indent opType = 738 - opStructFieldOmitEmptyUint16Indent opType = 739 - opStructFieldOmitEmptyUint32Indent opType = 740 - opStructFieldOmitEmptyUint64Indent opType = 741 - opStructFieldOmitEmptyFloat32Indent opType = 742 - opStructFieldOmitEmptyFloat64Indent opType = 743 - opStructFieldOmitEmptyBoolIndent opType = 744 - opStructFieldOmitEmptyStringIndent opType = 745 - opStructFieldOmitEmptyBytesIndent opType = 746 - opStructFieldOmitEmptyArrayIndent opType = 747 - opStructFieldOmitEmptyMapIndent opType = 748 - opStructFieldOmitEmptyMapLoadIndent opType = 749 - opStructFieldOmitEmptySliceIndent opType = 750 - opStructFieldOmitEmptyStructIndent opType = 751 - opStructFieldOmitEmptyMarshalJSONIndent opType = 752 - opStructFieldOmitEmptyMarshalTextIndent opType = 753 - opStructFieldStringTagIntIndent opType = 754 - opStructFieldStringTagInt8Indent opType = 755 - opStructFieldStringTagInt16Indent opType = 756 - opStructFieldStringTagInt32Indent opType = 757 - opStructFieldStringTagInt64Indent opType = 758 - opStructFieldStringTagUintIndent opType = 759 - opStructFieldStringTagUint8Indent opType = 760 - opStructFieldStringTagUint16Indent opType = 761 - opStructFieldStringTagUint32Indent opType = 762 - opStructFieldStringTagUint64Indent opType = 763 - opStructFieldStringTagFloat32Indent opType = 764 - opStructFieldStringTagFloat64Indent opType = 765 - opStructFieldStringTagBoolIndent opType = 766 - opStructFieldStringTagStringIndent opType = 767 - opStructFieldStringTagBytesIndent opType = 768 - opStructFieldStringTagArrayIndent opType = 769 - opStructFieldStringTagMapIndent opType = 770 - opStructFieldStringTagMapLoadIndent opType = 771 - opStructFieldStringTagSliceIndent opType = 772 - opStructFieldStringTagStructIndent opType = 773 - opStructFieldStringTagMarshalJSONIndent opType = 774 - opStructFieldStringTagMarshalTextIndent opType = 775 + opStructFieldPtrInt opType = 344 + opStructFieldPtrInt8 opType = 345 + opStructFieldPtrInt16 opType = 346 + opStructFieldPtrInt32 opType = 347 + opStructFieldPtrInt64 opType = 348 + opStructFieldPtrUint opType = 349 + opStructFieldPtrUint8 opType = 350 + opStructFieldPtrUint16 opType = 351 + opStructFieldPtrUint32 opType = 352 + opStructFieldPtrUint64 opType = 353 + opStructFieldPtrFloat32 opType = 354 + opStructFieldPtrFloat64 opType = 355 + opStructFieldPtrBool opType = 356 + opStructFieldPtrString opType = 357 + opStructFieldPtrBytes opType = 358 + opStructFieldPtrArray opType = 359 + opStructFieldPtrMap opType = 360 + opStructFieldPtrMapLoad opType = 361 + opStructFieldPtrSlice opType = 362 + opStructFieldPtrStruct opType = 363 + opStructFieldPtrMarshalJSON opType = 364 + opStructFieldPtrMarshalText opType = 365 + opStructFieldOmitEmptyInt opType = 366 + opStructFieldOmitEmptyInt8 opType = 367 + opStructFieldOmitEmptyInt16 opType = 368 + opStructFieldOmitEmptyInt32 opType = 369 + opStructFieldOmitEmptyInt64 opType = 370 + opStructFieldOmitEmptyUint opType = 371 + opStructFieldOmitEmptyUint8 opType = 372 + opStructFieldOmitEmptyUint16 opType = 373 + opStructFieldOmitEmptyUint32 opType = 374 + opStructFieldOmitEmptyUint64 opType = 375 + opStructFieldOmitEmptyFloat32 opType = 376 + opStructFieldOmitEmptyFloat64 opType = 377 + opStructFieldOmitEmptyBool opType = 378 + opStructFieldOmitEmptyString opType = 379 + opStructFieldOmitEmptyBytes opType = 380 + opStructFieldOmitEmptyArray opType = 381 + opStructFieldOmitEmptyMap opType = 382 + opStructFieldOmitEmptyMapLoad opType = 383 + opStructFieldOmitEmptySlice opType = 384 + opStructFieldOmitEmptyStruct opType = 385 + opStructFieldOmitEmptyMarshalJSON opType = 386 + opStructFieldOmitEmptyMarshalText opType = 387 + opStructFieldStringTagInt opType = 388 + opStructFieldStringTagInt8 opType = 389 + opStructFieldStringTagInt16 opType = 390 + opStructFieldStringTagInt32 opType = 391 + opStructFieldStringTagInt64 opType = 392 + opStructFieldStringTagUint opType = 393 + opStructFieldStringTagUint8 opType = 394 + opStructFieldStringTagUint16 opType = 395 + opStructFieldStringTagUint32 opType = 396 + opStructFieldStringTagUint64 opType = 397 + opStructFieldStringTagFloat32 opType = 398 + opStructFieldStringTagFloat64 opType = 399 + opStructFieldStringTagBool opType = 400 + opStructFieldStringTagString opType = 401 + opStructFieldStringTagBytes opType = 402 + opStructFieldStringTagArray opType = 403 + opStructFieldStringTagMap opType = 404 + opStructFieldStringTagMapLoad opType = 405 + opStructFieldStringTagSlice opType = 406 + opStructFieldStringTagStruct opType = 407 + opStructFieldStringTagMarshalJSON opType = 408 + opStructFieldStringTagMarshalText opType = 409 + opEndIndent opType = 410 + opInterfaceIndent opType = 411 + opInterfaceEndIndent opType = 412 + opPtrIndent opType = 413 + opSliceHeadIndent opType = 414 + opRootSliceHeadIndent opType = 415 + opSliceElemIndent opType = 416 + opRootSliceElemIndent opType = 417 + opSliceEndIndent opType = 418 + opArrayHeadIndent opType = 419 + opArrayElemIndent opType = 420 + opArrayEndIndent opType = 421 + opMapHeadIndent opType = 422 + opMapHeadLoadIndent opType = 423 + opMapKeyIndent opType = 424 + opMapValueIndent opType = 425 + opMapEndIndent opType = 426 + opStructFieldHeadIndent opType = 427 + opStructFieldHeadOmitEmptyIndent opType = 428 + opStructFieldHeadStringTagIndent opType = 429 + opStructFieldAnonymousHeadIndent opType = 430 + opStructFieldAnonymousHeadOmitEmptyIndent opType = 431 + opStructFieldPtrAnonymousHeadOmitEmptyIndent opType = 432 + opStructFieldAnonymousHeadStringTagIndent opType = 433 + opStructFieldPtrAnonymousHeadStringTagIndent opType = 434 + opStructFieldPtrHeadIndent opType = 435 + opStructFieldPtrHeadOmitEmptyIndent opType = 436 + opStructFieldPtrHeadStringTagIndent opType = 437 + opStructFieldPtrAnonymousHeadIndent opType = 438 + opStructFieldIndent opType = 439 + opStructFieldOmitEmptyIndent opType = 440 + opStructFieldStringTagIndent opType = 441 + opStructFieldRecursiveIndent opType = 442 + opStructFieldRecursiveEndIndent opType = 443 + opStructEndIndent opType = 444 + opStructAnonymousEndIndent opType = 445 + opIntIndent opType = 446 + opInt8Indent opType = 447 + opInt16Indent opType = 448 + opInt32Indent opType = 449 + opInt64Indent opType = 450 + opUintIndent opType = 451 + opUint8Indent opType = 452 + opUint16Indent opType = 453 + opUint32Indent opType = 454 + opUint64Indent opType = 455 + opFloat32Indent opType = 456 + opFloat64Indent opType = 457 + opBoolIndent opType = 458 + opStringIndent opType = 459 + opBytesIndent opType = 460 + opArrayIndent opType = 461 + opMapIndent opType = 462 + opMapLoadIndent opType = 463 + opSliceIndent opType = 464 + opStructIndent opType = 465 + opMarshalJSONIndent opType = 466 + opMarshalTextIndent opType = 467 + opStructFieldHeadIntIndent opType = 468 + opStructFieldHeadInt8Indent opType = 469 + opStructFieldHeadInt16Indent opType = 470 + opStructFieldHeadInt32Indent opType = 471 + opStructFieldHeadInt64Indent opType = 472 + opStructFieldHeadUintIndent opType = 473 + opStructFieldHeadUint8Indent opType = 474 + opStructFieldHeadUint16Indent opType = 475 + opStructFieldHeadUint32Indent opType = 476 + opStructFieldHeadUint64Indent opType = 477 + opStructFieldHeadFloat32Indent opType = 478 + opStructFieldHeadFloat64Indent opType = 479 + opStructFieldHeadBoolIndent opType = 480 + opStructFieldHeadStringIndent opType = 481 + opStructFieldHeadBytesIndent opType = 482 + opStructFieldHeadArrayIndent opType = 483 + opStructFieldHeadMapIndent opType = 484 + opStructFieldHeadMapLoadIndent opType = 485 + opStructFieldHeadSliceIndent opType = 486 + opStructFieldHeadStructIndent opType = 487 + opStructFieldHeadMarshalJSONIndent opType = 488 + opStructFieldHeadMarshalTextIndent opType = 489 + opStructFieldHeadOmitEmptyIntIndent opType = 490 + opStructFieldHeadOmitEmptyInt8Indent opType = 491 + opStructFieldHeadOmitEmptyInt16Indent opType = 492 + opStructFieldHeadOmitEmptyInt32Indent opType = 493 + opStructFieldHeadOmitEmptyInt64Indent opType = 494 + opStructFieldHeadOmitEmptyUintIndent opType = 495 + opStructFieldHeadOmitEmptyUint8Indent opType = 496 + opStructFieldHeadOmitEmptyUint16Indent opType = 497 + opStructFieldHeadOmitEmptyUint32Indent opType = 498 + opStructFieldHeadOmitEmptyUint64Indent opType = 499 + opStructFieldHeadOmitEmptyFloat32Indent opType = 500 + opStructFieldHeadOmitEmptyFloat64Indent opType = 501 + opStructFieldHeadOmitEmptyBoolIndent opType = 502 + opStructFieldHeadOmitEmptyStringIndent opType = 503 + opStructFieldHeadOmitEmptyBytesIndent opType = 504 + opStructFieldHeadOmitEmptyArrayIndent opType = 505 + opStructFieldHeadOmitEmptyMapIndent opType = 506 + opStructFieldHeadOmitEmptyMapLoadIndent opType = 507 + opStructFieldHeadOmitEmptySliceIndent opType = 508 + opStructFieldHeadOmitEmptyStructIndent opType = 509 + opStructFieldHeadOmitEmptyMarshalJSONIndent opType = 510 + opStructFieldHeadOmitEmptyMarshalTextIndent opType = 511 + opStructFieldHeadStringTagIntIndent opType = 512 + opStructFieldHeadStringTagInt8Indent opType = 513 + opStructFieldHeadStringTagInt16Indent opType = 514 + opStructFieldHeadStringTagInt32Indent opType = 515 + opStructFieldHeadStringTagInt64Indent opType = 516 + opStructFieldHeadStringTagUintIndent opType = 517 + opStructFieldHeadStringTagUint8Indent opType = 518 + opStructFieldHeadStringTagUint16Indent opType = 519 + opStructFieldHeadStringTagUint32Indent opType = 520 + opStructFieldHeadStringTagUint64Indent opType = 521 + opStructFieldHeadStringTagFloat32Indent opType = 522 + opStructFieldHeadStringTagFloat64Indent opType = 523 + opStructFieldHeadStringTagBoolIndent opType = 524 + opStructFieldHeadStringTagStringIndent opType = 525 + opStructFieldHeadStringTagBytesIndent opType = 526 + opStructFieldHeadStringTagArrayIndent opType = 527 + opStructFieldHeadStringTagMapIndent opType = 528 + opStructFieldHeadStringTagMapLoadIndent opType = 529 + opStructFieldHeadStringTagSliceIndent opType = 530 + opStructFieldHeadStringTagStructIndent opType = 531 + opStructFieldHeadStringTagMarshalJSONIndent opType = 532 + opStructFieldHeadStringTagMarshalTextIndent opType = 533 + opStructFieldAnonymousHeadIntIndent opType = 534 + opStructFieldAnonymousHeadInt8Indent opType = 535 + opStructFieldAnonymousHeadInt16Indent opType = 536 + opStructFieldAnonymousHeadInt32Indent opType = 537 + opStructFieldAnonymousHeadInt64Indent opType = 538 + opStructFieldAnonymousHeadUintIndent opType = 539 + opStructFieldAnonymousHeadUint8Indent opType = 540 + opStructFieldAnonymousHeadUint16Indent opType = 541 + opStructFieldAnonymousHeadUint32Indent opType = 542 + opStructFieldAnonymousHeadUint64Indent opType = 543 + opStructFieldAnonymousHeadFloat32Indent opType = 544 + opStructFieldAnonymousHeadFloat64Indent opType = 545 + opStructFieldAnonymousHeadBoolIndent opType = 546 + opStructFieldAnonymousHeadStringIndent opType = 547 + opStructFieldAnonymousHeadBytesIndent opType = 548 + opStructFieldAnonymousHeadArrayIndent opType = 549 + opStructFieldAnonymousHeadMapIndent opType = 550 + opStructFieldAnonymousHeadMapLoadIndent opType = 551 + opStructFieldAnonymousHeadSliceIndent opType = 552 + opStructFieldAnonymousHeadStructIndent opType = 553 + opStructFieldAnonymousHeadMarshalJSONIndent opType = 554 + opStructFieldAnonymousHeadMarshalTextIndent opType = 555 + opStructFieldAnonymousHeadOmitEmptyIntIndent opType = 556 + opStructFieldAnonymousHeadOmitEmptyInt8Indent opType = 557 + opStructFieldAnonymousHeadOmitEmptyInt16Indent opType = 558 + opStructFieldAnonymousHeadOmitEmptyInt32Indent opType = 559 + opStructFieldAnonymousHeadOmitEmptyInt64Indent opType = 560 + opStructFieldAnonymousHeadOmitEmptyUintIndent opType = 561 + opStructFieldAnonymousHeadOmitEmptyUint8Indent opType = 562 + opStructFieldAnonymousHeadOmitEmptyUint16Indent opType = 563 + opStructFieldAnonymousHeadOmitEmptyUint32Indent opType = 564 + opStructFieldAnonymousHeadOmitEmptyUint64Indent opType = 565 + opStructFieldAnonymousHeadOmitEmptyFloat32Indent opType = 566 + opStructFieldAnonymousHeadOmitEmptyFloat64Indent opType = 567 + opStructFieldAnonymousHeadOmitEmptyBoolIndent opType = 568 + opStructFieldAnonymousHeadOmitEmptyStringIndent opType = 569 + opStructFieldAnonymousHeadOmitEmptyBytesIndent opType = 570 + opStructFieldAnonymousHeadOmitEmptyArrayIndent opType = 571 + opStructFieldAnonymousHeadOmitEmptyMapIndent opType = 572 + opStructFieldAnonymousHeadOmitEmptyMapLoadIndent opType = 573 + opStructFieldAnonymousHeadOmitEmptySliceIndent opType = 574 + opStructFieldAnonymousHeadOmitEmptyStructIndent opType = 575 + opStructFieldAnonymousHeadOmitEmptyMarshalJSONIndent opType = 576 + opStructFieldAnonymousHeadOmitEmptyMarshalTextIndent opType = 577 + opStructFieldAnonymousHeadStringTagIntIndent opType = 578 + opStructFieldAnonymousHeadStringTagInt8Indent opType = 579 + opStructFieldAnonymousHeadStringTagInt16Indent opType = 580 + opStructFieldAnonymousHeadStringTagInt32Indent opType = 581 + opStructFieldAnonymousHeadStringTagInt64Indent opType = 582 + opStructFieldAnonymousHeadStringTagUintIndent opType = 583 + opStructFieldAnonymousHeadStringTagUint8Indent opType = 584 + opStructFieldAnonymousHeadStringTagUint16Indent opType = 585 + opStructFieldAnonymousHeadStringTagUint32Indent opType = 586 + opStructFieldAnonymousHeadStringTagUint64Indent opType = 587 + opStructFieldAnonymousHeadStringTagFloat32Indent opType = 588 + opStructFieldAnonymousHeadStringTagFloat64Indent opType = 589 + opStructFieldAnonymousHeadStringTagBoolIndent opType = 590 + opStructFieldAnonymousHeadStringTagStringIndent opType = 591 + opStructFieldAnonymousHeadStringTagBytesIndent opType = 592 + opStructFieldAnonymousHeadStringTagArrayIndent opType = 593 + opStructFieldAnonymousHeadStringTagMapIndent opType = 594 + opStructFieldAnonymousHeadStringTagMapLoadIndent opType = 595 + opStructFieldAnonymousHeadStringTagSliceIndent opType = 596 + opStructFieldAnonymousHeadStringTagStructIndent opType = 597 + opStructFieldAnonymousHeadStringTagMarshalJSONIndent opType = 598 + opStructFieldAnonymousHeadStringTagMarshalTextIndent opType = 599 + opStructFieldPtrHeadIntIndent opType = 600 + opStructFieldPtrHeadInt8Indent opType = 601 + opStructFieldPtrHeadInt16Indent opType = 602 + opStructFieldPtrHeadInt32Indent opType = 603 + opStructFieldPtrHeadInt64Indent opType = 604 + opStructFieldPtrHeadUintIndent opType = 605 + opStructFieldPtrHeadUint8Indent opType = 606 + opStructFieldPtrHeadUint16Indent opType = 607 + opStructFieldPtrHeadUint32Indent opType = 608 + opStructFieldPtrHeadUint64Indent opType = 609 + opStructFieldPtrHeadFloat32Indent opType = 610 + opStructFieldPtrHeadFloat64Indent opType = 611 + opStructFieldPtrHeadBoolIndent opType = 612 + opStructFieldPtrHeadStringIndent opType = 613 + opStructFieldPtrHeadBytesIndent opType = 614 + opStructFieldPtrHeadArrayIndent opType = 615 + opStructFieldPtrHeadMapIndent opType = 616 + opStructFieldPtrHeadMapLoadIndent opType = 617 + opStructFieldPtrHeadSliceIndent opType = 618 + opStructFieldPtrHeadStructIndent opType = 619 + opStructFieldPtrHeadMarshalJSONIndent opType = 620 + opStructFieldPtrHeadMarshalTextIndent opType = 621 + opStructFieldPtrHeadOmitEmptyIntIndent opType = 622 + opStructFieldPtrHeadOmitEmptyInt8Indent opType = 623 + opStructFieldPtrHeadOmitEmptyInt16Indent opType = 624 + opStructFieldPtrHeadOmitEmptyInt32Indent opType = 625 + opStructFieldPtrHeadOmitEmptyInt64Indent opType = 626 + opStructFieldPtrHeadOmitEmptyUintIndent opType = 627 + opStructFieldPtrHeadOmitEmptyUint8Indent opType = 628 + opStructFieldPtrHeadOmitEmptyUint16Indent opType = 629 + opStructFieldPtrHeadOmitEmptyUint32Indent opType = 630 + opStructFieldPtrHeadOmitEmptyUint64Indent opType = 631 + opStructFieldPtrHeadOmitEmptyFloat32Indent opType = 632 + opStructFieldPtrHeadOmitEmptyFloat64Indent opType = 633 + opStructFieldPtrHeadOmitEmptyBoolIndent opType = 634 + opStructFieldPtrHeadOmitEmptyStringIndent opType = 635 + opStructFieldPtrHeadOmitEmptyBytesIndent opType = 636 + opStructFieldPtrHeadOmitEmptyArrayIndent opType = 637 + opStructFieldPtrHeadOmitEmptyMapIndent opType = 638 + opStructFieldPtrHeadOmitEmptyMapLoadIndent opType = 639 + opStructFieldPtrHeadOmitEmptySliceIndent opType = 640 + opStructFieldPtrHeadOmitEmptyStructIndent opType = 641 + opStructFieldPtrHeadOmitEmptyMarshalJSONIndent opType = 642 + opStructFieldPtrHeadOmitEmptyMarshalTextIndent opType = 643 + opStructFieldPtrHeadStringTagIntIndent opType = 644 + opStructFieldPtrHeadStringTagInt8Indent opType = 645 + opStructFieldPtrHeadStringTagInt16Indent opType = 646 + opStructFieldPtrHeadStringTagInt32Indent opType = 647 + opStructFieldPtrHeadStringTagInt64Indent opType = 648 + opStructFieldPtrHeadStringTagUintIndent opType = 649 + opStructFieldPtrHeadStringTagUint8Indent opType = 650 + opStructFieldPtrHeadStringTagUint16Indent opType = 651 + opStructFieldPtrHeadStringTagUint32Indent opType = 652 + opStructFieldPtrHeadStringTagUint64Indent opType = 653 + opStructFieldPtrHeadStringTagFloat32Indent opType = 654 + opStructFieldPtrHeadStringTagFloat64Indent opType = 655 + opStructFieldPtrHeadStringTagBoolIndent opType = 656 + opStructFieldPtrHeadStringTagStringIndent opType = 657 + opStructFieldPtrHeadStringTagBytesIndent opType = 658 + opStructFieldPtrHeadStringTagArrayIndent opType = 659 + opStructFieldPtrHeadStringTagMapIndent opType = 660 + opStructFieldPtrHeadStringTagMapLoadIndent opType = 661 + opStructFieldPtrHeadStringTagSliceIndent opType = 662 + opStructFieldPtrHeadStringTagStructIndent opType = 663 + opStructFieldPtrHeadStringTagMarshalJSONIndent opType = 664 + opStructFieldPtrHeadStringTagMarshalTextIndent opType = 665 + opStructFieldPtrAnonymousHeadIntIndent opType = 666 + opStructFieldPtrAnonymousHeadInt8Indent opType = 667 + opStructFieldPtrAnonymousHeadInt16Indent opType = 668 + opStructFieldPtrAnonymousHeadInt32Indent opType = 669 + opStructFieldPtrAnonymousHeadInt64Indent opType = 670 + opStructFieldPtrAnonymousHeadUintIndent opType = 671 + opStructFieldPtrAnonymousHeadUint8Indent opType = 672 + opStructFieldPtrAnonymousHeadUint16Indent opType = 673 + opStructFieldPtrAnonymousHeadUint32Indent opType = 674 + opStructFieldPtrAnonymousHeadUint64Indent opType = 675 + opStructFieldPtrAnonymousHeadFloat32Indent opType = 676 + opStructFieldPtrAnonymousHeadFloat64Indent opType = 677 + opStructFieldPtrAnonymousHeadBoolIndent opType = 678 + opStructFieldPtrAnonymousHeadStringIndent opType = 679 + opStructFieldPtrAnonymousHeadBytesIndent opType = 680 + opStructFieldPtrAnonymousHeadArrayIndent opType = 681 + opStructFieldPtrAnonymousHeadMapIndent opType = 682 + opStructFieldPtrAnonymousHeadMapLoadIndent opType = 683 + opStructFieldPtrAnonymousHeadSliceIndent opType = 684 + opStructFieldPtrAnonymousHeadStructIndent opType = 685 + opStructFieldPtrAnonymousHeadMarshalJSONIndent opType = 686 + opStructFieldPtrAnonymousHeadMarshalTextIndent opType = 687 + opStructFieldPtrAnonymousHeadOmitEmptyIntIndent opType = 688 + opStructFieldPtrAnonymousHeadOmitEmptyInt8Indent opType = 689 + opStructFieldPtrAnonymousHeadOmitEmptyInt16Indent opType = 690 + opStructFieldPtrAnonymousHeadOmitEmptyInt32Indent opType = 691 + opStructFieldPtrAnonymousHeadOmitEmptyInt64Indent opType = 692 + opStructFieldPtrAnonymousHeadOmitEmptyUintIndent opType = 693 + opStructFieldPtrAnonymousHeadOmitEmptyUint8Indent opType = 694 + opStructFieldPtrAnonymousHeadOmitEmptyUint16Indent opType = 695 + opStructFieldPtrAnonymousHeadOmitEmptyUint32Indent opType = 696 + opStructFieldPtrAnonymousHeadOmitEmptyUint64Indent opType = 697 + opStructFieldPtrAnonymousHeadOmitEmptyFloat32Indent opType = 698 + opStructFieldPtrAnonymousHeadOmitEmptyFloat64Indent opType = 699 + opStructFieldPtrAnonymousHeadOmitEmptyBoolIndent opType = 700 + opStructFieldPtrAnonymousHeadOmitEmptyStringIndent opType = 701 + opStructFieldPtrAnonymousHeadOmitEmptyBytesIndent opType = 702 + opStructFieldPtrAnonymousHeadOmitEmptyArrayIndent opType = 703 + opStructFieldPtrAnonymousHeadOmitEmptyMapIndent opType = 704 + opStructFieldPtrAnonymousHeadOmitEmptyMapLoadIndent opType = 705 + opStructFieldPtrAnonymousHeadOmitEmptySliceIndent opType = 706 + opStructFieldPtrAnonymousHeadOmitEmptyStructIndent opType = 707 + opStructFieldPtrAnonymousHeadOmitEmptyMarshalJSONIndent opType = 708 + opStructFieldPtrAnonymousHeadOmitEmptyMarshalTextIndent opType = 709 + opStructFieldPtrAnonymousHeadStringTagIntIndent opType = 710 + opStructFieldPtrAnonymousHeadStringTagInt8Indent opType = 711 + opStructFieldPtrAnonymousHeadStringTagInt16Indent opType = 712 + opStructFieldPtrAnonymousHeadStringTagInt32Indent opType = 713 + opStructFieldPtrAnonymousHeadStringTagInt64Indent opType = 714 + opStructFieldPtrAnonymousHeadStringTagUintIndent opType = 715 + opStructFieldPtrAnonymousHeadStringTagUint8Indent opType = 716 + opStructFieldPtrAnonymousHeadStringTagUint16Indent opType = 717 + opStructFieldPtrAnonymousHeadStringTagUint32Indent opType = 718 + opStructFieldPtrAnonymousHeadStringTagUint64Indent opType = 719 + opStructFieldPtrAnonymousHeadStringTagFloat32Indent opType = 720 + opStructFieldPtrAnonymousHeadStringTagFloat64Indent opType = 721 + opStructFieldPtrAnonymousHeadStringTagBoolIndent opType = 722 + opStructFieldPtrAnonymousHeadStringTagStringIndent opType = 723 + opStructFieldPtrAnonymousHeadStringTagBytesIndent opType = 724 + opStructFieldPtrAnonymousHeadStringTagArrayIndent opType = 725 + opStructFieldPtrAnonymousHeadStringTagMapIndent opType = 726 + opStructFieldPtrAnonymousHeadStringTagMapLoadIndent opType = 727 + opStructFieldPtrAnonymousHeadStringTagSliceIndent opType = 728 + opStructFieldPtrAnonymousHeadStringTagStructIndent opType = 729 + opStructFieldPtrAnonymousHeadStringTagMarshalJSONIndent opType = 730 + opStructFieldPtrAnonymousHeadStringTagMarshalTextIndent opType = 731 + opStructFieldIntIndent opType = 732 + opStructFieldInt8Indent opType = 733 + opStructFieldInt16Indent opType = 734 + opStructFieldInt32Indent opType = 735 + opStructFieldInt64Indent opType = 736 + opStructFieldUintIndent opType = 737 + opStructFieldUint8Indent opType = 738 + opStructFieldUint16Indent opType = 739 + opStructFieldUint32Indent opType = 740 + opStructFieldUint64Indent opType = 741 + opStructFieldFloat32Indent opType = 742 + opStructFieldFloat64Indent opType = 743 + opStructFieldBoolIndent opType = 744 + opStructFieldStringIndent opType = 745 + opStructFieldBytesIndent opType = 746 + opStructFieldArrayIndent opType = 747 + opStructFieldMapIndent opType = 748 + opStructFieldMapLoadIndent opType = 749 + opStructFieldSliceIndent opType = 750 + opStructFieldStructIndent opType = 751 + opStructFieldMarshalJSONIndent opType = 752 + opStructFieldMarshalTextIndent opType = 753 + opStructFieldPtrIntIndent opType = 754 + opStructFieldPtrInt8Indent opType = 755 + opStructFieldPtrInt16Indent opType = 756 + opStructFieldPtrInt32Indent opType = 757 + opStructFieldPtrInt64Indent opType = 758 + opStructFieldPtrUintIndent opType = 759 + opStructFieldPtrUint8Indent opType = 760 + opStructFieldPtrUint16Indent opType = 761 + opStructFieldPtrUint32Indent opType = 762 + opStructFieldPtrUint64Indent opType = 763 + opStructFieldPtrFloat32Indent opType = 764 + opStructFieldPtrFloat64Indent opType = 765 + opStructFieldPtrBoolIndent opType = 766 + opStructFieldPtrStringIndent opType = 767 + opStructFieldPtrBytesIndent opType = 768 + opStructFieldPtrArrayIndent opType = 769 + opStructFieldPtrMapIndent opType = 770 + opStructFieldPtrMapLoadIndent opType = 771 + opStructFieldPtrSliceIndent opType = 772 + opStructFieldPtrStructIndent opType = 773 + opStructFieldPtrMarshalJSONIndent opType = 774 + opStructFieldPtrMarshalTextIndent opType = 775 + opStructFieldOmitEmptyIntIndent opType = 776 + opStructFieldOmitEmptyInt8Indent opType = 777 + opStructFieldOmitEmptyInt16Indent opType = 778 + opStructFieldOmitEmptyInt32Indent opType = 779 + opStructFieldOmitEmptyInt64Indent opType = 780 + opStructFieldOmitEmptyUintIndent opType = 781 + opStructFieldOmitEmptyUint8Indent opType = 782 + opStructFieldOmitEmptyUint16Indent opType = 783 + opStructFieldOmitEmptyUint32Indent opType = 784 + opStructFieldOmitEmptyUint64Indent opType = 785 + opStructFieldOmitEmptyFloat32Indent opType = 786 + opStructFieldOmitEmptyFloat64Indent opType = 787 + opStructFieldOmitEmptyBoolIndent opType = 788 + opStructFieldOmitEmptyStringIndent opType = 789 + opStructFieldOmitEmptyBytesIndent opType = 790 + opStructFieldOmitEmptyArrayIndent opType = 791 + opStructFieldOmitEmptyMapIndent opType = 792 + opStructFieldOmitEmptyMapLoadIndent opType = 793 + opStructFieldOmitEmptySliceIndent opType = 794 + opStructFieldOmitEmptyStructIndent opType = 795 + opStructFieldOmitEmptyMarshalJSONIndent opType = 796 + opStructFieldOmitEmptyMarshalTextIndent opType = 797 + opStructFieldStringTagIntIndent opType = 798 + opStructFieldStringTagInt8Indent opType = 799 + opStructFieldStringTagInt16Indent opType = 800 + opStructFieldStringTagInt32Indent opType = 801 + opStructFieldStringTagInt64Indent opType = 802 + opStructFieldStringTagUintIndent opType = 803 + opStructFieldStringTagUint8Indent opType = 804 + opStructFieldStringTagUint16Indent opType = 805 + opStructFieldStringTagUint32Indent opType = 806 + opStructFieldStringTagUint64Indent opType = 807 + opStructFieldStringTagFloat32Indent opType = 808 + opStructFieldStringTagFloat64Indent opType = 809 + opStructFieldStringTagBoolIndent opType = 810 + opStructFieldStringTagStringIndent opType = 811 + opStructFieldStringTagBytesIndent opType = 812 + opStructFieldStringTagArrayIndent opType = 813 + opStructFieldStringTagMapIndent opType = 814 + opStructFieldStringTagMapLoadIndent opType = 815 + opStructFieldStringTagSliceIndent opType = 816 + opStructFieldStringTagStructIndent opType = 817 + opStructFieldStringTagMarshalJSONIndent opType = 818 + opStructFieldStringTagMarshalTextIndent opType = 819 ) func (t opType) String() string { @@ -1488,6 +1532,50 @@ func (t opType) String() string { return "StructFieldMarshalJSON" case opStructFieldMarshalText: return "StructFieldMarshalText" + case opStructFieldPtrInt: + return "StructFieldPtrInt" + case opStructFieldPtrInt8: + return "StructFieldPtrInt8" + case opStructFieldPtrInt16: + return "StructFieldPtrInt16" + case opStructFieldPtrInt32: + return "StructFieldPtrInt32" + case opStructFieldPtrInt64: + return "StructFieldPtrInt64" + case opStructFieldPtrUint: + return "StructFieldPtrUint" + case opStructFieldPtrUint8: + return "StructFieldPtrUint8" + case opStructFieldPtrUint16: + return "StructFieldPtrUint16" + case opStructFieldPtrUint32: + return "StructFieldPtrUint32" + case opStructFieldPtrUint64: + return "StructFieldPtrUint64" + case opStructFieldPtrFloat32: + return "StructFieldPtrFloat32" + case opStructFieldPtrFloat64: + return "StructFieldPtrFloat64" + case opStructFieldPtrBool: + return "StructFieldPtrBool" + case opStructFieldPtrString: + return "StructFieldPtrString" + case opStructFieldPtrBytes: + return "StructFieldPtrBytes" + case opStructFieldPtrArray: + return "StructFieldPtrArray" + case opStructFieldPtrMap: + return "StructFieldPtrMap" + case opStructFieldPtrMapLoad: + return "StructFieldPtrMapLoad" + case opStructFieldPtrSlice: + return "StructFieldPtrSlice" + case opStructFieldPtrStruct: + return "StructFieldPtrStruct" + case opStructFieldPtrMarshalJSON: + return "StructFieldPtrMarshalJSON" + case opStructFieldPtrMarshalText: + return "StructFieldPtrMarshalText" case opStructFieldOmitEmptyInt: return "StructFieldOmitEmptyInt" case opStructFieldOmitEmptyInt8: @@ -2264,6 +2352,50 @@ func (t opType) String() string { return "StructFieldMarshalJSONIndent" case opStructFieldMarshalTextIndent: return "StructFieldMarshalTextIndent" + case opStructFieldPtrIntIndent: + return "StructFieldPtrIntIndent" + case opStructFieldPtrInt8Indent: + return "StructFieldPtrInt8Indent" + case opStructFieldPtrInt16Indent: + return "StructFieldPtrInt16Indent" + case opStructFieldPtrInt32Indent: + return "StructFieldPtrInt32Indent" + case opStructFieldPtrInt64Indent: + return "StructFieldPtrInt64Indent" + case opStructFieldPtrUintIndent: + return "StructFieldPtrUintIndent" + case opStructFieldPtrUint8Indent: + return "StructFieldPtrUint8Indent" + case opStructFieldPtrUint16Indent: + return "StructFieldPtrUint16Indent" + case opStructFieldPtrUint32Indent: + return "StructFieldPtrUint32Indent" + case opStructFieldPtrUint64Indent: + return "StructFieldPtrUint64Indent" + case opStructFieldPtrFloat32Indent: + return "StructFieldPtrFloat32Indent" + case opStructFieldPtrFloat64Indent: + return "StructFieldPtrFloat64Indent" + case opStructFieldPtrBoolIndent: + return "StructFieldPtrBoolIndent" + case opStructFieldPtrStringIndent: + return "StructFieldPtrStringIndent" + case opStructFieldPtrBytesIndent: + return "StructFieldPtrBytesIndent" + case opStructFieldPtrArrayIndent: + return "StructFieldPtrArrayIndent" + case opStructFieldPtrMapIndent: + return "StructFieldPtrMapIndent" + case opStructFieldPtrMapLoadIndent: + return "StructFieldPtrMapLoadIndent" + case opStructFieldPtrSliceIndent: + return "StructFieldPtrSliceIndent" + case opStructFieldPtrStructIndent: + return "StructFieldPtrStructIndent" + case opStructFieldPtrMarshalJSONIndent: + return "StructFieldPtrMarshalJSONIndent" + case opStructFieldPtrMarshalTextIndent: + return "StructFieldPtrMarshalTextIndent" case opStructFieldOmitEmptyIntIndent: return "StructFieldOmitEmptyIntIndent" case opStructFieldOmitEmptyInt8Indent: @@ -3046,6 +3178,50 @@ func (t opType) codeType() codeType { return codeStructField case opStructFieldMarshalText: return codeStructField + case opStructFieldPtrInt: + return codeStructField + case opStructFieldPtrInt8: + return codeStructField + case opStructFieldPtrInt16: + return codeStructField + case opStructFieldPtrInt32: + return codeStructField + case opStructFieldPtrInt64: + return codeStructField + case opStructFieldPtrUint: + return codeStructField + case opStructFieldPtrUint8: + return codeStructField + case opStructFieldPtrUint16: + return codeStructField + case opStructFieldPtrUint32: + return codeStructField + case opStructFieldPtrUint64: + return codeStructField + case opStructFieldPtrFloat32: + return codeStructField + case opStructFieldPtrFloat64: + return codeStructField + case opStructFieldPtrBool: + return codeStructField + case opStructFieldPtrString: + return codeStructField + case opStructFieldPtrBytes: + return codeStructField + case opStructFieldPtrArray: + return codeStructField + case opStructFieldPtrMap: + return codeStructField + case opStructFieldPtrMapLoad: + return codeStructField + case opStructFieldPtrSlice: + return codeStructField + case opStructFieldPtrStruct: + return codeStructField + case opStructFieldPtrMarshalJSON: + return codeStructField + case opStructFieldPtrMarshalText: + return codeStructField case opStructFieldOmitEmptyInt: return codeStructField case opStructFieldOmitEmptyInt8: @@ -3822,6 +3998,50 @@ func (t opType) codeType() codeType { return codeStructField case opStructFieldMarshalTextIndent: return codeStructField + case opStructFieldPtrIntIndent: + return codeStructField + case opStructFieldPtrInt8Indent: + return codeStructField + case opStructFieldPtrInt16Indent: + return codeStructField + case opStructFieldPtrInt32Indent: + return codeStructField + case opStructFieldPtrInt64Indent: + return codeStructField + case opStructFieldPtrUintIndent: + return codeStructField + case opStructFieldPtrUint8Indent: + return codeStructField + case opStructFieldPtrUint16Indent: + return codeStructField + case opStructFieldPtrUint32Indent: + return codeStructField + case opStructFieldPtrUint64Indent: + return codeStructField + case opStructFieldPtrFloat32Indent: + return codeStructField + case opStructFieldPtrFloat64Indent: + return codeStructField + case opStructFieldPtrBoolIndent: + return codeStructField + case opStructFieldPtrStringIndent: + return codeStructField + case opStructFieldPtrBytesIndent: + return codeStructField + case opStructFieldPtrArrayIndent: + return codeStructField + case opStructFieldPtrMapIndent: + return codeStructField + case opStructFieldPtrMapLoadIndent: + return codeStructField + case opStructFieldPtrSliceIndent: + return codeStructField + case opStructFieldPtrStructIndent: + return codeStructField + case opStructFieldPtrMarshalJSONIndent: + return codeStructField + case opStructFieldPtrMarshalTextIndent: + return codeStructField case opStructFieldOmitEmptyIntIndent: return codeStructField case opStructFieldOmitEmptyInt8Indent: @@ -4604,6 +4824,50 @@ func (t opType) toIndent() opType { return opStructFieldMarshalJSONIndent case opStructFieldMarshalText: return opStructFieldMarshalTextIndent + case opStructFieldPtrInt: + return opStructFieldPtrIntIndent + case opStructFieldPtrInt8: + return opStructFieldPtrInt8Indent + case opStructFieldPtrInt16: + return opStructFieldPtrInt16Indent + case opStructFieldPtrInt32: + return opStructFieldPtrInt32Indent + case opStructFieldPtrInt64: + return opStructFieldPtrInt64Indent + case opStructFieldPtrUint: + return opStructFieldPtrUintIndent + case opStructFieldPtrUint8: + return opStructFieldPtrUint8Indent + case opStructFieldPtrUint16: + return opStructFieldPtrUint16Indent + case opStructFieldPtrUint32: + return opStructFieldPtrUint32Indent + case opStructFieldPtrUint64: + return opStructFieldPtrUint64Indent + case opStructFieldPtrFloat32: + return opStructFieldPtrFloat32Indent + case opStructFieldPtrFloat64: + return opStructFieldPtrFloat64Indent + case opStructFieldPtrBool: + return opStructFieldPtrBoolIndent + case opStructFieldPtrString: + return opStructFieldPtrStringIndent + case opStructFieldPtrBytes: + return opStructFieldPtrBytesIndent + case opStructFieldPtrArray: + return opStructFieldPtrArrayIndent + case opStructFieldPtrMap: + return opStructFieldPtrMapIndent + case opStructFieldPtrMapLoad: + return opStructFieldPtrMapLoadIndent + case opStructFieldPtrSlice: + return opStructFieldPtrSliceIndent + case opStructFieldPtrStruct: + return opStructFieldPtrStructIndent + case opStructFieldPtrMarshalJSON: + return opStructFieldPtrMarshalJSONIndent + case opStructFieldPtrMarshalText: + return opStructFieldPtrMarshalTextIndent case opStructFieldOmitEmptyInt: return opStructFieldOmitEmptyIntIndent case opStructFieldOmitEmptyInt8: @@ -5380,6 +5644,50 @@ func (t opType) toIndent() opType { return opStructFieldMarshalJSONIndent case opStructFieldMarshalTextIndent: return opStructFieldMarshalTextIndent + case opStructFieldPtrIntIndent: + return opStructFieldPtrIntIndent + case opStructFieldPtrInt8Indent: + return opStructFieldPtrInt8Indent + case opStructFieldPtrInt16Indent: + return opStructFieldPtrInt16Indent + case opStructFieldPtrInt32Indent: + return opStructFieldPtrInt32Indent + case opStructFieldPtrInt64Indent: + return opStructFieldPtrInt64Indent + case opStructFieldPtrUintIndent: + return opStructFieldPtrUintIndent + case opStructFieldPtrUint8Indent: + return opStructFieldPtrUint8Indent + case opStructFieldPtrUint16Indent: + return opStructFieldPtrUint16Indent + case opStructFieldPtrUint32Indent: + return opStructFieldPtrUint32Indent + case opStructFieldPtrUint64Indent: + return opStructFieldPtrUint64Indent + case opStructFieldPtrFloat32Indent: + return opStructFieldPtrFloat32Indent + case opStructFieldPtrFloat64Indent: + return opStructFieldPtrFloat64Indent + case opStructFieldPtrBoolIndent: + return opStructFieldPtrBoolIndent + case opStructFieldPtrStringIndent: + return opStructFieldPtrStringIndent + case opStructFieldPtrBytesIndent: + return opStructFieldPtrBytesIndent + case opStructFieldPtrArrayIndent: + return opStructFieldPtrArrayIndent + case opStructFieldPtrMapIndent: + return opStructFieldPtrMapIndent + case opStructFieldPtrMapLoadIndent: + return opStructFieldPtrMapLoadIndent + case opStructFieldPtrSliceIndent: + return opStructFieldPtrSliceIndent + case opStructFieldPtrStructIndent: + return opStructFieldPtrStructIndent + case opStructFieldPtrMarshalJSONIndent: + return opStructFieldPtrMarshalJSONIndent + case opStructFieldPtrMarshalTextIndent: + return opStructFieldPtrMarshalTextIndent case opStructFieldOmitEmptyIntIndent: return opStructFieldOmitEmptyIntIndent case opStructFieldOmitEmptyInt8Indent: diff --git a/encode_vm.go b/encode_vm.go index 378e82a..2771328 100644 --- a/encode_vm.go +++ b/encode_vm.go @@ -105,6 +105,11 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { code = code.next case opInterface: ptr := load(ctxptr, code.idx) + if ptr == 0 { + e.encodeNull() + code = code.next + break + } v := *(*interface{})(unsafe.Pointer(&interfaceHeader{ typ: code.typ, ptr: unsafe.Pointer(ptr), @@ -463,6 +468,11 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { } else { // load pointer ptr = uintptr(*(*unsafe.Pointer)(unsafe.Pointer(ptr))) + if ptr == 0 { + e.encodeNull() + code = code.end.next + break + } e.encodeByte('{') mlen := maplen(unsafe.Pointer(ptr)) if mlen > 0 { @@ -612,6 +622,12 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { } else { // load pointer ptr = uintptr(*(*unsafe.Pointer)(unsafe.Pointer(ptr))) + if ptr == 0 { + e.encodeIndent(code.indent) + e.encodeNull() + code = code.end.next + break + } mlen := maplen(unsafe.Pointer(ptr)) if mlen > 0 { e.encodeBytes([]byte{'{', '\n'}) @@ -783,10 +799,13 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { ctxptr = ctx.ptr() + offset ptrOffset = offset case opStructFieldPtrHead: - ptr := load(ctxptr, code.idx) - if ptr != 0 { - store(ctxptr, code.idx, e.ptrToPtr(ptr)) + p := load(ctxptr, code.idx) + if p == 0 { + e.encodeNull() + code = code.end.next + break } + store(ctxptr, code.idx, e.ptrToPtr(p)) fallthrough case opStructFieldHead: ptr := load(ctxptr, code.idx) @@ -815,7 +834,13 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { store(ctxptr, code.idx, ptr) } case opStructFieldPtrHeadInt: - store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) + p := load(ctxptr, code.idx) + if p == 0 { + e.encodeNull() + code = code.end.next + break + } + store(ctxptr, code.idx, e.ptrToPtr(p)) fallthrough case opStructFieldHeadInt: ptr := load(ctxptr, code.idx) @@ -825,7 +850,7 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { } else { e.encodeBytes([]byte{'{', '}'}) } - code = code.end + code = code.end.next } else { e.encodeByte('{') e.encodeKey(code) @@ -838,14 +863,20 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { case opStructFieldAnonymousHeadInt: ptr := load(ctxptr, code.idx) if ptr == 0 { - code = code.end + code = code.end.next } else { e.encodeKey(code) e.encodeInt(e.ptrToInt(ptr + code.offset)) code = code.next } case opStructFieldPtrHeadInt8: - store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) + p := load(ctxptr, code.idx) + if p == 0 { + e.encodeNull() + code = code.end.next + break + } + store(ctxptr, code.idx, e.ptrToPtr(p)) fallthrough case opStructFieldHeadInt8: ptr := load(ctxptr, code.idx) @@ -855,7 +886,7 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { } else { e.encodeBytes([]byte{'{', '}'}) } - code = code.end + code = code.end.next } else { e.encodeByte('{') e.encodeKey(code) @@ -868,14 +899,20 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { case opStructFieldAnonymousHeadInt8: ptr := load(ctxptr, code.idx) if ptr == 0 { - code = code.end + code = code.end.next } else { e.encodeKey(code) e.encodeInt8(e.ptrToInt8(ptr + code.offset)) code = code.next } case opStructFieldPtrHeadInt16: - store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) + p := load(ctxptr, code.idx) + if p == 0 { + e.encodeNull() + code = code.end.next + break + } + store(ctxptr, code.idx, e.ptrToPtr(p)) fallthrough case opStructFieldHeadInt16: ptr := load(ctxptr, code.idx) @@ -885,7 +922,7 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { } else { e.encodeBytes([]byte{'{', '}'}) } - code = code.end + code = code.end.next } else { e.encodeByte('{') e.encodeKey(code) @@ -898,14 +935,20 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { case opStructFieldAnonymousHeadInt16: ptr := load(ctxptr, code.idx) if ptr == 0 { - code = code.end + code = code.end.next } else { e.encodeKey(code) e.encodeInt16(e.ptrToInt16(ptr + code.offset)) code = code.next } case opStructFieldPtrHeadInt32: - store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) + p := load(ctxptr, code.idx) + if p == 0 { + e.encodeNull() + code = code.end.next + break + } + store(ctxptr, code.idx, e.ptrToPtr(p)) fallthrough case opStructFieldHeadInt32: ptr := load(ctxptr, code.idx) @@ -915,7 +958,7 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { } else { e.encodeBytes([]byte{'{', '}'}) } - code = code.end + code = code.end.next } else { e.encodeByte('{') e.encodeKey(code) @@ -928,14 +971,20 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { case opStructFieldAnonymousHeadInt32: ptr := load(ctxptr, code.idx) if ptr == 0 { - code = code.end + code = code.end.next } else { e.encodeKey(code) e.encodeInt32(e.ptrToInt32(ptr + code.offset)) code = code.next } case opStructFieldPtrHeadInt64: - store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) + p := load(ctxptr, code.idx) + if p == 0 { + e.encodeNull() + code = code.end.next + break + } + store(ctxptr, code.idx, e.ptrToPtr(p)) fallthrough case opStructFieldHeadInt64: ptr := load(ctxptr, code.idx) @@ -945,7 +994,7 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { } else { e.encodeBytes([]byte{'{', '}'}) } - code = code.end + code = code.end.next } else { e.encodeByte('{') e.encodeKey(code) @@ -958,14 +1007,20 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { case opStructFieldAnonymousHeadInt64: ptr := load(ctxptr, code.idx) if ptr == 0 { - code = code.end + code = code.end.next } else { e.encodeKey(code) e.encodeInt64(e.ptrToInt64(ptr + code.offset)) code = code.next } case opStructFieldPtrHeadUint: - store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) + p := load(ctxptr, code.idx) + if p == 0 { + e.encodeNull() + code = code.end.next + break + } + store(ctxptr, code.idx, e.ptrToPtr(p)) fallthrough case opStructFieldHeadUint: ptr := load(ctxptr, code.idx) @@ -975,7 +1030,7 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { } else { e.encodeBytes([]byte{'{', '}'}) } - code = code.end + code = code.end.next } else { e.encodeByte('{') e.encodeKey(code) @@ -988,14 +1043,20 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { case opStructFieldAnonymousHeadUint: ptr := load(ctxptr, code.idx) if ptr == 0 { - code = code.end + code = code.end.next } else { e.encodeKey(code) e.encodeUint(e.ptrToUint(ptr + code.offset)) code = code.next } case opStructFieldPtrHeadUint8: - store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) + p := load(ctxptr, code.idx) + if p == 0 { + e.encodeNull() + code = code.end.next + break + } + store(ctxptr, code.idx, e.ptrToPtr(p)) fallthrough case opStructFieldHeadUint8: ptr := load(ctxptr, code.idx) @@ -1005,7 +1066,7 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { } else { e.encodeBytes([]byte{'{', '}'}) } - code = code.end + code = code.end.next } else { e.encodeByte('{') e.encodeKey(code) @@ -1018,14 +1079,20 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { case opStructFieldAnonymousHeadUint8: ptr := load(ctxptr, code.idx) if ptr == 0 { - code = code.end + code = code.end.next } else { e.encodeKey(code) e.encodeUint8(e.ptrToUint8(ptr + code.offset)) code = code.next } case opStructFieldPtrHeadUint16: - store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) + p := load(ctxptr, code.idx) + if p == 0 { + e.encodeNull() + code = code.end.next + break + } + store(ctxptr, code.idx, e.ptrToPtr(p)) fallthrough case opStructFieldHeadUint16: ptr := load(ctxptr, code.idx) @@ -1035,7 +1102,7 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { } else { e.encodeBytes([]byte{'{', '}'}) } - code = code.end + code = code.end.next } else { e.encodeByte('{') e.encodeKey(code) @@ -1048,14 +1115,20 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { case opStructFieldAnonymousHeadUint16: ptr := load(ctxptr, code.idx) if ptr == 0 { - code = code.end + code = code.end.next } else { e.encodeKey(code) e.encodeUint16(e.ptrToUint16(ptr + code.offset)) code = code.next } case opStructFieldPtrHeadUint32: - store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) + p := load(ctxptr, code.idx) + if p == 0 { + e.encodeNull() + code = code.end.next + break + } + store(ctxptr, code.idx, e.ptrToPtr(p)) fallthrough case opStructFieldHeadUint32: ptr := load(ctxptr, code.idx) @@ -1065,7 +1138,7 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { } else { e.encodeBytes([]byte{'{', '}'}) } - code = code.end + code = code.end.next } else { e.encodeByte('{') e.encodeKey(code) @@ -1078,14 +1151,20 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { case opStructFieldAnonymousHeadUint32: ptr := load(ctxptr, code.idx) if ptr == 0 { - code = code.end + code = code.end.next } else { e.encodeKey(code) e.encodeUint32(e.ptrToUint32(ptr + code.offset)) code = code.next } case opStructFieldPtrHeadUint64: - store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) + p := load(ctxptr, code.idx) + if p == 0 { + e.encodeNull() + code = code.end.next + break + } + store(ctxptr, code.idx, e.ptrToPtr(p)) fallthrough case opStructFieldHeadUint64: ptr := load(ctxptr, code.idx) @@ -1095,7 +1174,7 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { } else { e.encodeBytes([]byte{'{', '}'}) } - code = code.end + code = code.end.next } else { e.encodeByte('{') e.encodeKey(code) @@ -1108,14 +1187,20 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { case opStructFieldAnonymousHeadUint64: ptr := load(ctxptr, code.idx) if ptr == 0 { - code = code.end + code = code.end.next } else { e.encodeKey(code) e.encodeUint64(e.ptrToUint64(ptr + code.offset)) code = code.next } case opStructFieldPtrHeadFloat32: - store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) + p := load(ctxptr, code.idx) + if p == 0 { + e.encodeNull() + code = code.end.next + break + } + store(ctxptr, code.idx, e.ptrToPtr(p)) fallthrough case opStructFieldHeadFloat32: ptr := load(ctxptr, code.idx) @@ -1125,7 +1210,7 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { } else { e.encodeBytes([]byte{'{', '}'}) } - code = code.end + code = code.end.next } else { e.encodeByte('{') e.encodeKey(code) @@ -1138,14 +1223,20 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { case opStructFieldAnonymousHeadFloat32: ptr := load(ctxptr, code.idx) if ptr == 0 { - code = code.end + code = code.end.next } else { e.encodeKey(code) e.encodeFloat32(e.ptrToFloat32(ptr + code.offset)) code = code.next } case opStructFieldPtrHeadFloat64: - store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) + p := load(ctxptr, code.idx) + if p == 0 { + e.encodeNull() + code = code.end.next + break + } + store(ctxptr, code.idx, e.ptrToPtr(p)) fallthrough case opStructFieldHeadFloat64: ptr := load(ctxptr, code.idx) @@ -1155,7 +1246,7 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { } else { e.encodeBytes([]byte{'{', '}'}) } - code = code.end + code = code.end.next } else { v := e.ptrToFloat64(ptr + code.offset) if math.IsInf(v, 0) || math.IsNaN(v) { @@ -1175,7 +1266,7 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { case opStructFieldAnonymousHeadFloat64: ptr := load(ctxptr, code.idx) if ptr == 0 { - code = code.end + code = code.end.next } else { v := e.ptrToFloat64(ptr + code.offset) if math.IsInf(v, 0) || math.IsNaN(v) { @@ -1189,7 +1280,13 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { code = code.next } case opStructFieldPtrHeadString: - store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) + p := load(ctxptr, code.idx) + if p == 0 { + e.encodeNull() + code = code.end.next + break + } + store(ctxptr, code.idx, e.ptrToPtr(p)) fallthrough case opStructFieldHeadString: ptr := load(ctxptr, code.idx) @@ -1199,7 +1296,7 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { } else { e.encodeBytes([]byte{'{', '}'}) } - code = code.end + code = code.end.next } else { e.encodeByte('{') e.encodeKey(code) @@ -1212,14 +1309,20 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { case opStructFieldAnonymousHeadString: ptr := load(ctxptr, code.idx) if ptr == 0 { - code = code.end + code = code.end.next } else { e.encodeKey(code) e.encodeString(e.ptrToString(ptr + code.offset)) code = code.next } case opStructFieldPtrHeadBool: - store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) + p := load(ctxptr, code.idx) + if p == 0 { + e.encodeNull() + code = code.end.next + break + } + store(ctxptr, code.idx, e.ptrToPtr(p)) fallthrough case opStructFieldHeadBool: ptr := load(ctxptr, code.idx) @@ -1229,7 +1332,7 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { } else { e.encodeBytes([]byte{'{', '}'}) } - code = code.end + code = code.end.next } else { e.encodeByte('{') e.encodeKey(code) @@ -1242,14 +1345,20 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { case opStructFieldAnonymousHeadBool: ptr := load(ctxptr, code.idx) if ptr == 0 { - code = code.end + code = code.end.next } else { e.encodeKey(code) e.encodeBool(e.ptrToBool(ptr + code.offset)) code = code.next } case opStructFieldPtrHeadBytes: - store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) + p := load(ctxptr, code.idx) + if p == 0 { + e.encodeNull() + code = code.end.next + break + } + store(ctxptr, code.idx, e.ptrToPtr(p)) fallthrough case opStructFieldHeadBytes: ptr := load(ctxptr, code.idx) @@ -1259,7 +1368,7 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { } else { e.encodeBytes([]byte{'{', '}'}) } - code = code.end + code = code.end.next } else { e.encodeByte('{') e.encodeKey(code) @@ -1272,14 +1381,20 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { case opStructFieldAnonymousHeadBytes: ptr := load(ctxptr, code.idx) if ptr == 0 { - code = code.end + code = code.end.next } else { e.encodeKey(code) e.encodeByteSlice(e.ptrToBytes(ptr + code.offset)) code = code.next } case opStructFieldPtrHeadArray: - store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) + p := load(ctxptr, code.idx) + if p == 0 { + e.encodeNull() + code = code.end.next + break + } + store(ctxptr, code.idx, e.ptrToPtr(p)) fallthrough case opStructFieldHeadArray: ptr := load(ctxptr, code.idx) + code.offset @@ -1289,7 +1404,7 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { } else { e.encodeBytes([]byte{'[', ']'}) } - code = code.end + code = code.end.next } else { e.encodeByte('{') if !code.anonymousKey { @@ -1304,14 +1419,20 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { case opStructFieldAnonymousHeadArray: ptr := load(ctxptr, code.idx) + code.offset if ptr == 0 { - code = code.end + code = code.end.next } else { e.encodeKey(code) store(ctxptr, code.idx, ptr) code = code.next } case opStructFieldPtrHeadSlice: - store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) + p := load(ctxptr, code.idx) + if p == 0 { + e.encodeNull() + code = code.end.next + break + } + store(ctxptr, code.idx, e.ptrToPtr(p)) fallthrough case opStructFieldHeadSlice: ptr := load(ctxptr, code.idx) @@ -1322,7 +1443,7 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { } else { e.encodeBytes([]byte{'[', ']'}) } - code = code.end + code = code.end.next } else { e.encodeByte('{') if !code.anonymousKey { @@ -1338,20 +1459,26 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { ptr := load(ctxptr, code.idx) p := ptr + code.offset if p == 0 { - code = code.end + code = code.end.next } else { e.encodeKey(code) store(ctxptr, code.idx, p) code = code.next } case opStructFieldPtrHeadMarshalJSON: - store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) + p := load(ctxptr, code.idx) + if p == 0 { + e.encodeNull() + code = code.end.next + break + } + store(ctxptr, code.idx, e.ptrToPtr(p)) fallthrough case opStructFieldHeadMarshalJSON: ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeNull() - code = code.end + code = code.end.next } else { e.encodeByte('{') e.encodeKey(code) @@ -1391,7 +1518,7 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { case opStructFieldAnonymousHeadMarshalJSON: ptr := load(ctxptr, code.idx) if ptr == 0 { - code = code.end + code = code.end.next } else { e.encodeKey(code) v := *(*interface{})(unsafe.Pointer(&interfaceHeader{ @@ -1401,7 +1528,7 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { rv := reflect.ValueOf(v) if rv.Type().Kind() == reflect.Interface && rv.IsNil() { e.encodeNull() - code = code.end + code = code.end.next break } b, err := rv.Interface().(Marshaler).MarshalJSON() @@ -1425,13 +1552,19 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { code = code.next } case opStructFieldPtrHeadMarshalText: - store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) + p := load(ctxptr, code.idx) + if p == 0 { + e.encodeNull() + code = code.end.next + break + } + store(ctxptr, code.idx, e.ptrToPtr(p)) fallthrough case opStructFieldHeadMarshalText: ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeNull() - code = code.end + code = code.end.next } else { e.encodeByte('{') e.encodeKey(code) @@ -1461,7 +1594,7 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { case opStructFieldAnonymousHeadMarshalText: ptr := load(ctxptr, code.idx) if ptr == 0 { - code = code.end + code = code.end.next } else { e.encodeKey(code) v := *(*interface{})(unsafe.Pointer(&interfaceHeader{ @@ -1471,7 +1604,7 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { rv := reflect.ValueOf(v) if rv.Type().Kind() == reflect.Interface && rv.IsNil() { e.encodeNull() - code = code.end + code = code.end.next break } bytes, err := rv.Interface().(encoding.TextMarshaler).MarshalText() @@ -1500,7 +1633,7 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { // not exists fields e.encodeIndent(code.indent) e.encodeBytes([]byte{'{', '}'}) - code = code.next + code = code.end.next store(ctxptr, code.idx, ptr) } else { e.encodeIndent(code.indent) @@ -1523,7 +1656,7 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { } else { e.encodeBytes([]byte{'{', '}'}) } - code = code.end + code = code.end.next } else { e.encodeBytes([]byte{'{', '\n'}) e.encodeIndent(code.indent + 1) @@ -1540,7 +1673,7 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() - code = code.end + code = code.end.next } else { e.encodeIndent(code.indent) e.encodeBytes([]byte{'{', '\n'}) @@ -1557,7 +1690,7 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { ptr := load(ctxptr, code.idx) if ptr == 0 { e.encodeNull() - code = code.end + code = code.end.next } else { e.encodeIndent(code.indent) e.encodeBytes([]byte{'{', '\n'}) @@ -1575,7 +1708,7 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() - code = code.end + code = code.end.next } else { e.encodeIndent(code.indent) e.encodeBytes([]byte{'{', '\n'}) @@ -1593,7 +1726,7 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() - code = code.end + code = code.end.next } else { e.encodeIndent(code.indent) e.encodeBytes([]byte{'{', '\n'}) @@ -1611,7 +1744,7 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() - code = code.end + code = code.end.next } else { e.encodeIndent(code.indent) e.encodeBytes([]byte{'{', '\n'}) @@ -1629,7 +1762,7 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() - code = code.end + code = code.end.next } else { e.encodeIndent(code.indent) e.encodeBytes([]byte{'{', '\n'}) @@ -1647,7 +1780,7 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() - code = code.end + code = code.end.next } else { e.encodeIndent(code.indent) e.encodeBytes([]byte{'{', '\n'}) @@ -1665,7 +1798,7 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() - code = code.end + code = code.end.next } else { e.encodeIndent(code.indent) e.encodeBytes([]byte{'{', '\n'}) @@ -1683,7 +1816,7 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() - code = code.end + code = code.end.next } else { e.encodeIndent(code.indent) e.encodeBytes([]byte{'{', '\n'}) @@ -1701,7 +1834,7 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() - code = code.end + code = code.end.next } else { e.encodeIndent(code.indent) e.encodeBytes([]byte{'{', '\n'}) @@ -1719,7 +1852,7 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() - code = code.end + code = code.end.next } else { v := e.ptrToFloat64(ptr) if math.IsInf(v, 0) || math.IsNaN(v) { @@ -1744,7 +1877,7 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() - code = code.end + code = code.end.next } else { e.encodeIndent(code.indent) e.encodeBytes([]byte{'{', '\n'}) @@ -1762,7 +1895,7 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() - code = code.end + code = code.end.next } else { e.encodeIndent(code.indent) e.encodeBytes([]byte{'{', '\n'}) @@ -1780,7 +1913,7 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { if ptr == 0 { e.encodeIndent(code.indent) e.encodeNull() - code = code.end + code = code.end.next } else { e.encodeIndent(code.indent) e.encodeBytes([]byte{'{', '\n'}) @@ -4062,6 +4195,19 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { ptr := load(ctxptr, code.headIdx) + code.offset code = code.next store(ctxptr, code.idx, ptr) + case opStructFieldPtrInt: + if e.buf[len(e.buf)-1] != '{' { + e.encodeByte(',') + } + e.encodeKey(code) + ptr := load(ctxptr, code.headIdx) + p := e.ptrToPtr(ptr + code.offset) + if p == 0 { + e.encodeNull() + } else { + e.encodeInt(e.ptrToInt(p)) + } + code = code.next case opStructFieldInt: if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') @@ -4070,6 +4216,19 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { e.encodeKey(code) e.encodeInt(e.ptrToInt(ptr + code.offset)) code = code.next + case opStructFieldPtrInt8: + if e.buf[len(e.buf)-1] != '{' { + e.encodeByte(',') + } + e.encodeKey(code) + ptr := load(ctxptr, code.headIdx) + p := e.ptrToPtr(ptr + code.offset) + if p == 0 { + e.encodeNull() + } else { + e.encodeInt8(e.ptrToInt8(p)) + } + code = code.next case opStructFieldInt8: if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') @@ -4078,6 +4237,19 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { e.encodeKey(code) e.encodeInt8(e.ptrToInt8(ptr + code.offset)) code = code.next + case opStructFieldPtrInt16: + if e.buf[len(e.buf)-1] != '{' { + e.encodeByte(',') + } + e.encodeKey(code) + ptr := load(ctxptr, code.headIdx) + p := e.ptrToPtr(ptr + code.offset) + if p == 0 { + e.encodeNull() + } else { + e.encodeInt16(e.ptrToInt16(p)) + } + code = code.next case opStructFieldInt16: if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') @@ -4086,6 +4258,19 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { e.encodeKey(code) e.encodeInt16(e.ptrToInt16(ptr + code.offset)) code = code.next + case opStructFieldPtrInt32: + if e.buf[len(e.buf)-1] != '{' { + e.encodeByte(',') + } + e.encodeKey(code) + ptr := load(ctxptr, code.headIdx) + p := e.ptrToPtr(ptr + code.offset) + if p == 0 { + e.encodeNull() + } else { + e.encodeInt32(e.ptrToInt32(p)) + } + code = code.next case opStructFieldInt32: if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') @@ -4094,6 +4279,19 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { e.encodeKey(code) e.encodeInt32(e.ptrToInt32(ptr + code.offset)) code = code.next + case opStructFieldPtrInt64: + if e.buf[len(e.buf)-1] != '{' { + e.encodeByte(',') + } + e.encodeKey(code) + ptr := load(ctxptr, code.headIdx) + p := e.ptrToPtr(ptr + code.offset) + if p == 0 { + e.encodeNull() + } else { + e.encodeInt64(e.ptrToInt64(p)) + } + code = code.next case opStructFieldInt64: if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') @@ -4102,6 +4300,19 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { e.encodeKey(code) e.encodeInt64(e.ptrToInt64(ptr + code.offset)) code = code.next + case opStructFieldPtrUint: + if e.buf[len(e.buf)-1] != '{' { + e.encodeByte(',') + } + e.encodeKey(code) + ptr := load(ctxptr, code.headIdx) + p := e.ptrToPtr(ptr + code.offset) + if p == 0 { + e.encodeNull() + } else { + e.encodeUint(e.ptrToUint(p)) + } + code = code.next case opStructFieldUint: if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') @@ -4110,6 +4321,19 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { e.encodeKey(code) e.encodeUint(e.ptrToUint(ptr + code.offset)) code = code.next + case opStructFieldPtrUint8: + if e.buf[len(e.buf)-1] != '{' { + e.encodeByte(',') + } + e.encodeKey(code) + ptr := load(ctxptr, code.headIdx) + p := e.ptrToPtr(ptr + code.offset) + if p == 0 { + e.encodeNull() + } else { + e.encodeUint8(e.ptrToUint8(p)) + } + code = code.next case opStructFieldUint8: if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') @@ -4118,6 +4342,19 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { e.encodeKey(code) e.encodeUint8(e.ptrToUint8(ptr + code.offset)) code = code.next + case opStructFieldPtrUint16: + if e.buf[len(e.buf)-1] != '{' { + e.encodeByte(',') + } + e.encodeKey(code) + ptr := load(ctxptr, code.headIdx) + p := e.ptrToPtr(ptr + code.offset) + if p == 0 { + e.encodeNull() + } else { + e.encodeUint16(e.ptrToUint16(p)) + } + code = code.next case opStructFieldUint16: if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') @@ -4126,6 +4363,19 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { e.encodeKey(code) e.encodeUint16(e.ptrToUint16(ptr + code.offset)) code = code.next + case opStructFieldPtrUint32: + if e.buf[len(e.buf)-1] != '{' { + e.encodeByte(',') + } + e.encodeKey(code) + ptr := load(ctxptr, code.headIdx) + p := e.ptrToPtr(ptr + code.offset) + if p == 0 { + e.encodeNull() + } else { + e.encodeUint32(e.ptrToUint32(p)) + } + code = code.next case opStructFieldUint32: if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') @@ -4134,6 +4384,19 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { e.encodeKey(code) e.encodeUint32(e.ptrToUint32(ptr + code.offset)) code = code.next + case opStructFieldPtrUint64: + if e.buf[len(e.buf)-1] != '{' { + e.encodeByte(',') + } + e.encodeKey(code) + ptr := load(ctxptr, code.headIdx) + p := e.ptrToPtr(ptr + code.offset) + if p == 0 { + e.encodeNull() + } else { + e.encodeUint64(e.ptrToUint64(p)) + } + code = code.next case opStructFieldUint64: if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') @@ -4142,6 +4405,19 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { e.encodeKey(code) e.encodeUint64(e.ptrToUint64(ptr + code.offset)) code = code.next + case opStructFieldPtrFloat32: + if e.buf[len(e.buf)-1] != '{' { + e.encodeByte(',') + } + e.encodeKey(code) + ptr := load(ctxptr, code.headIdx) + p := e.ptrToPtr(ptr + code.offset) + if p == 0 { + e.encodeNull() + } else { + e.encodeFloat32(e.ptrToFloat32(p)) + } + code = code.next case opStructFieldFloat32: if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') @@ -4150,6 +4426,27 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { e.encodeKey(code) e.encodeFloat32(e.ptrToFloat32(ptr + code.offset)) code = code.next + case opStructFieldPtrFloat64: + if e.buf[len(e.buf)-1] != '{' { + e.encodeByte(',') + } + e.encodeKey(code) + ptr := load(ctxptr, code.headIdx) + p := e.ptrToPtr(ptr + code.offset) + if p == 0 { + e.encodeNull() + code = code.next + break + } + v := e.ptrToFloat64(p) + if math.IsInf(v, 0) || math.IsNaN(v) { + return &UnsupportedValueError{ + Value: reflect.ValueOf(v), + Str: strconv.FormatFloat(v, 'g', -1, 64), + } + } + e.encodeFloat64(v) + code = code.next case opStructFieldFloat64: if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') @@ -4165,6 +4462,19 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { } e.encodeFloat64(v) code = code.next + case opStructFieldPtrString: + if e.buf[len(e.buf)-1] != '{' { + e.encodeByte(',') + } + e.encodeKey(code) + ptr := load(ctxptr, code.headIdx) + p := e.ptrToPtr(ptr + code.offset) + if p == 0 { + e.encodeNull() + } else { + e.encodeString(e.ptrToString(p)) + } + code = code.next case opStructFieldString: if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') @@ -4173,6 +4483,19 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { e.encodeKey(code) e.encodeString(e.ptrToString(ptr + code.offset)) code = code.next + case opStructFieldPtrBool: + if e.buf[len(e.buf)-1] != '{' { + e.encodeByte(',') + } + e.encodeKey(code) + ptr := load(ctxptr, code.headIdx) + p := e.ptrToPtr(ptr + code.offset) + if p == 0 { + e.encodeNull() + } else { + e.encodeBool(e.ptrToBool(p)) + } + code = code.next case opStructFieldBool: if e.buf[len(e.buf)-1] != '{' { e.encodeByte(',') diff --git a/example_text_marshaling_test.go b/example_text_marshaling_test.go index a4df116..090cd63 100644 --- a/example_text_marshaling_test.go +++ b/example_text_marshaling_test.go @@ -15,19 +15,19 @@ import ( type Size int const ( - Unrecognized Size = iota - Small - Large + unrecognized Size = iota + small + large ) func (s *Size) UnmarshalText(text []byte) error { switch strings.ToLower(string(text)) { default: - *s = Unrecognized + *s = unrecognized case "small": - *s = Small + *s = small case "large": - *s = Large + *s = large } return nil } @@ -37,9 +37,9 @@ func (s Size) MarshalText() ([]byte, error) { switch s { default: name = "unrecognized" - case Small: + case small: name = "small" - case Large: + case large: name = "large" } return []byte(name), nil @@ -58,7 +58,7 @@ func Example_textMarshalJSON() { } fmt.Printf("Inventory Counts:\n* Small: %d\n* Large: %d\n* Unrecognized: %d\n", - counts[Small], counts[Large], counts[Unrecognized]) + counts[small], counts[large], counts[unrecognized]) // Output: // Inventory Counts: