Merge pull request #162 from goccy/feature/fix-marshaler

Fix encoding of MarshalJSON of function type
This commit is contained in:
Masaaki Goshima 2021-03-22 21:49:15 +09:00 committed by GitHub
commit 9903d614e3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 108 additions and 72 deletions

View File

@ -39,6 +39,16 @@ func (c *coverPtrMarshalJSONString) MarshalJSON() ([]byte, error) {
return []byte(c.C), nil return []byte(c.C), nil
} }
type coverFuncMarshalJSON func()
func (f coverFuncMarshalJSON) MarshalJSON() ([]byte, error) {
if f == nil {
return []byte(`null`), nil
}
f()
return []byte(`"func"`), nil
}
func TestCoverMarshalJSON(t *testing.T) { func TestCoverMarshalJSON(t *testing.T) {
type structMarshalJSON struct { type structMarshalJSON struct {
A coverMarshalJSON `json:"a"` A coverMarshalJSON `json:"a"`
@ -82,6 +92,31 @@ func TestCoverMarshalJSON(t *testing.T) {
name string name string
data interface{} data interface{}
}{ }{
{
name: "FuncMarshalJSON",
data: coverFuncMarshalJSON(func() {}),
},
{
name: "StructFuncMarshalJSON",
data: struct {
A coverFuncMarshalJSON
}{A: func() {}},
},
{
name: "StructFuncMarshalJSONMultiFields",
data: struct {
A coverFuncMarshalJSON
B coverFuncMarshalJSON
}{A: func() {}, B: func() {}},
},
{
name: "PtrStructFuncMarshalJSONMultiFields",
data: &struct {
A coverFuncMarshalJSON
B coverFuncMarshalJSON
C coverFuncMarshalJSON
}{A: func() {}, B: nil, C: func() {}},
},
{ {
name: "MarshalJSON", name: "MarshalJSON",
data: coverMarshalJSON{A: 1}, data: coverMarshalJSON{A: 1},
@ -3652,22 +3687,24 @@ func TestCoverMarshalJSON(t *testing.T) {
}, },
} }
for _, test := range tests { for _, test := range tests {
for _, indent := range []bool{true, false} { t.Run(test.name, func(t *testing.T) {
for _, htmlEscape := range []bool{true, false} { for _, indent := range []bool{true, false} {
var buf bytes.Buffer for _, htmlEscape := range []bool{true, false} {
enc := json.NewEncoder(&buf) var buf bytes.Buffer
enc.SetEscapeHTML(htmlEscape) enc := json.NewEncoder(&buf)
if indent { enc.SetEscapeHTML(htmlEscape)
enc.SetIndent("", " ") if indent {
} enc.SetIndent("", " ")
if err := enc.Encode(test.data); err != nil { }
t.Fatalf("%s(htmlEscape:%v,indent:%v): %+v: %s", test.name, htmlEscape, indent, test.data, err) if err := enc.Encode(test.data); err != nil {
} t.Fatalf("%s(htmlEscape:%v,indent:%v): %+v: %s", test.name, htmlEscape, indent, test.data, err)
stdresult := encodeByEncodingJSON(test.data, indent, htmlEscape) }
if buf.String() != stdresult { stdresult := encodeByEncodingJSON(test.data, indent, htmlEscape)
t.Errorf("%s(htmlEscape:%v,indent:%v): doesn't compatible with encoding/json. expected %q but got %q", test.name, htmlEscape, indent, stdresult, buf.String()) if buf.String() != stdresult {
t.Errorf("%s(htmlEscape:%v,indent:%v): doesn't compatible with encoding/json. expected %q but got %q", test.name, htmlEscape, indent, stdresult, buf.String())
}
} }
} }
} })
} }
} }

View File

@ -506,6 +506,7 @@ func compileMarshalJSON(ctx *compileContext) (*Opcode, error) {
if !typ.Implements(marshalJSONType) && runtime.PtrTo(typ).Implements(marshalJSONType) { if !typ.Implements(marshalJSONType) && runtime.PtrTo(typ).Implements(marshalJSONType) {
code.AddrForMarshaler = true code.AddrForMarshaler = true
} }
code.IsNilableType = isNilableType(typ)
ctx.incIndex() ctx.incIndex()
return code, nil return code, nil
} }
@ -516,6 +517,7 @@ func compileMarshalText(ctx *compileContext) (*Opcode, error) {
if !typ.Implements(marshalTextType) && runtime.PtrTo(typ).Implements(marshalTextType) { if !typ.Implements(marshalTextType) && runtime.PtrTo(typ).Implements(marshalTextType) {
code.AddrForMarshaler = true code.AddrForMarshaler = true
} }
code.IsNilableType = isNilableType(typ)
ctx.incIndex() ctx.incIndex()
return code, nil return code, nil
} }
@ -1274,12 +1276,10 @@ func isNilableType(typ *runtime.Type) bool {
switch typ.Kind() { switch typ.Kind() {
case reflect.Ptr: case reflect.Ptr:
return true return true
case reflect.Interface:
return true
case reflect.Slice:
return true
case reflect.Map: case reflect.Map:
return true return true
case reflect.Func:
return true
default: default:
return false return false
} }
@ -1418,6 +1418,7 @@ func compileStruct(ctx *compileContext, isPtr bool) (*Opcode, error) {
Nilcheck: nilcheck, Nilcheck: nilcheck,
AddrForMarshaler: addrForMarshaler, AddrForMarshaler: addrForMarshaler,
IsNextOpPtrType: strings.Contains(valueCode.Op.String(), "Ptr"), IsNextOpPtrType: strings.Contains(valueCode.Op.String(), "Ptr"),
IsNilableType: isNilableType,
} }
if fieldIdx == 0 { if fieldIdx == 0 {
fieldCode.HeadIdx = fieldCode.Idx fieldCode.HeadIdx = fieldCode.Idx

View File

@ -559,7 +559,7 @@ func AppendIndent(ctx *RuntimeContext, b []byte, indent int) []byte {
func IsNilForMarshaler(v interface{}) bool { func IsNilForMarshaler(v interface{}) bool {
rv := reflect.ValueOf(v) rv := reflect.ValueOf(v)
switch rv.Kind() { switch rv.Kind() {
case reflect.Interface, reflect.Map, reflect.Ptr: case reflect.Interface, reflect.Map, reflect.Ptr, reflect.Func:
return rv.IsNil() return rv.IsNil()
case reflect.Slice: case reflect.Slice:
return rv.IsNil() || rv.Len() == 0 return rv.IsNil() || rv.Len() == 0

View File

@ -26,6 +26,7 @@ type Opcode struct {
Nilcheck bool // whether needs to nilcheck or not Nilcheck bool // whether needs to nilcheck or not
AddrForMarshaler bool // whether needs to addr for marshaler or not AddrForMarshaler bool // whether needs to addr for marshaler or not
IsNextOpPtrType bool // whether next operation is ptr type or not IsNextOpPtrType bool // whether next operation is ptr type or not
IsNilableType bool // whether type is nilable or not
RshiftNum uint8 // use to take bit for judging whether negative integer or not RshiftNum uint8 // use to take bit for judging whether negative integer or not
Mask uint64 // mask for number Mask uint64 // mask for number
Indent int // indent number Indent int // indent number
@ -242,6 +243,7 @@ func (c *Opcode) copy(codeMap map[uintptr]*Opcode) *Opcode {
Nilcheck: c.Nilcheck, Nilcheck: c.Nilcheck,
AddrForMarshaler: c.AddrForMarshaler, AddrForMarshaler: c.AddrForMarshaler,
IsNextOpPtrType: c.IsNextOpPtrType, IsNextOpPtrType: c.IsNextOpPtrType,
IsNilableType: c.IsNilableType,
Indent: c.Indent, Indent: c.Indent,
Idx: c.Idx, Idx: c.Idx,
HeadIdx: c.HeadIdx, HeadIdx: c.HeadIdx,

View File

@ -3,7 +3,6 @@ package vm
import ( import (
"fmt" "fmt"
"math" "math"
"reflect"
"sort" "sort"
"unsafe" "unsafe"
@ -271,7 +270,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt
code = code.Next code = code.Next
break break
} }
if code.Type.Kind() == reflect.Ptr && code.Indirect { if code.IsNilableType && code.Indirect {
p = ptrToPtr(p) p = ptrToPtr(p)
} }
bb, err := appendMarshalJSON(code, b, ptrToInterface(code, p), false) bb, err := appendMarshalJSON(code, b, ptrToInterface(code, p), false)
@ -298,7 +297,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt
code = code.Next code = code.Next
break break
} }
if code.Type.Kind() == reflect.Ptr && code.Indirect { if code.IsNilableType && code.Indirect {
p = ptrToPtr(p) p = ptrToPtr(p)
} }
bb, err := appendMarshalText(code, b, ptrToInterface(code, p), false) bb, err := appendMarshalText(code, b, ptrToInterface(code, p), false)
@ -2711,7 +2710,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt
b = append(b, '{') b = append(b, '{')
} }
b = append(b, code.Key...) b = append(b, code.Key...)
if code.Type.Kind() == reflect.Ptr { if code.IsNilableType {
if code.Indirect || code.Op == encoder.OpStructPtrHeadMarshalJSON { if code.Indirect || code.Op == encoder.OpStructPtrHeadMarshalJSON {
p = ptrToPtr(p + code.Offset) p = ptrToPtr(p + code.Offset)
} }
@ -2755,7 +2754,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt
b = append(b, '{') b = append(b, '{')
} }
b = append(b, code.Key...) b = append(b, code.Key...)
if code.Type.Kind() == reflect.Ptr { if code.IsNilableType {
if code.Indirect || code.Op == encoder.OpStructPtrHeadStringTagMarshalJSON { if code.Indirect || code.Op == encoder.OpStructPtrHeadStringTagMarshalJSON {
p = ptrToPtr(p + code.Offset) p = ptrToPtr(p + code.Offset)
} }
@ -2798,7 +2797,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt
if !code.AnonymousHead { if !code.AnonymousHead {
b = append(b, '{') b = append(b, '{')
} }
if code.Type.Kind() == reflect.Ptr { if code.IsNilableType {
if code.Indirect || code.Op == encoder.OpStructPtrHeadOmitEmptyMarshalJSON { if code.Indirect || code.Op == encoder.OpStructPtrHeadOmitEmptyMarshalJSON {
p = ptrToPtr(p + code.Offset) p = ptrToPtr(p + code.Offset)
} }
@ -2924,7 +2923,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt
b = append(b, '{') b = append(b, '{')
} }
b = append(b, code.Key...) b = append(b, code.Key...)
if code.Type.Kind() == reflect.Ptr { if code.IsNilableType {
if code.Indirect || code.Op == encoder.OpStructPtrHeadMarshalText { if code.Indirect || code.Op == encoder.OpStructPtrHeadMarshalText {
p = ptrToPtr(p + code.Offset) p = ptrToPtr(p + code.Offset)
} }
@ -2968,7 +2967,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt
b = append(b, '{') b = append(b, '{')
} }
b = append(b, code.Key...) b = append(b, code.Key...)
if code.Type.Kind() == reflect.Ptr { if code.IsNilableType {
if code.Indirect || code.Op == encoder.OpStructPtrHeadStringTagMarshalText { if code.Indirect || code.Op == encoder.OpStructPtrHeadStringTagMarshalText {
p = ptrToPtr(p + code.Offset) p = ptrToPtr(p + code.Offset)
} }
@ -3011,7 +3010,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt
if !code.AnonymousHead { if !code.AnonymousHead {
b = append(b, '{') b = append(b, '{')
} }
if code.Type.Kind() == reflect.Ptr { if code.IsNilableType {
if code.Indirect || code.Op == encoder.OpStructPtrHeadOmitEmptyMarshalText { if code.Indirect || code.Op == encoder.OpStructPtrHeadOmitEmptyMarshalText {
p = ptrToPtr(p + code.Offset) p = ptrToPtr(p + code.Offset)
} }
@ -3623,7 +3622,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt
p := load(ctxptr, code.HeadIdx) p := load(ctxptr, code.HeadIdx)
b = append(b, code.Key...) b = append(b, code.Key...)
p += code.Offset p += code.Offset
if code.Type.Kind() == reflect.Ptr { if code.IsNilableType {
p = ptrToPtr(p) p = ptrToPtr(p)
} }
if p == 0 && code.Nilcheck { if p == 0 && code.Nilcheck {
@ -3640,7 +3639,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt
case encoder.OpStructFieldOmitEmptyMarshalJSON: case encoder.OpStructFieldOmitEmptyMarshalJSON:
p := load(ctxptr, code.HeadIdx) p := load(ctxptr, code.HeadIdx)
p += code.Offset p += code.Offset
if code.Type.Kind() == reflect.Ptr { if code.IsNilableType {
p = ptrToPtr(p) p = ptrToPtr(p)
} }
if p == 0 && code.Nilcheck { if p == 0 && code.Nilcheck {
@ -3685,7 +3684,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt
p := load(ctxptr, code.HeadIdx) p := load(ctxptr, code.HeadIdx)
b = append(b, code.Key...) b = append(b, code.Key...)
p += code.Offset p += code.Offset
if code.Type.Kind() == reflect.Ptr { if code.IsNilableType {
p = ptrToPtr(p) p = ptrToPtr(p)
} }
if p == 0 && code.Nilcheck { if p == 0 && code.Nilcheck {
@ -3702,7 +3701,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt
case encoder.OpStructFieldOmitEmptyMarshalText: case encoder.OpStructFieldOmitEmptyMarshalText:
p := load(ctxptr, code.HeadIdx) p := load(ctxptr, code.HeadIdx)
p += code.Offset p += code.Offset
if code.Type.Kind() == reflect.Ptr { if code.IsNilableType {
p = ptrToPtr(p) p = ptrToPtr(p)
} }
if p == 0 && code.Nilcheck { if p == 0 && code.Nilcheck {

View File

@ -3,7 +3,6 @@ package vm_escaped
import ( import (
"fmt" "fmt"
"math" "math"
"reflect"
"sort" "sort"
"unsafe" "unsafe"
@ -271,7 +270,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt
code = code.Next code = code.Next
break break
} }
if code.Type.Kind() == reflect.Ptr && code.Indirect { if code.IsNilableType && code.Indirect {
p = ptrToPtr(p) p = ptrToPtr(p)
} }
bb, err := appendMarshalJSON(code, b, ptrToInterface(code, p), true) bb, err := appendMarshalJSON(code, b, ptrToInterface(code, p), true)
@ -298,7 +297,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt
code = code.Next code = code.Next
break break
} }
if code.Type.Kind() == reflect.Ptr && code.Indirect { if code.IsNilableType && code.Indirect {
p = ptrToPtr(p) p = ptrToPtr(p)
} }
bb, err := appendMarshalText(code, b, ptrToInterface(code, p), true) bb, err := appendMarshalText(code, b, ptrToInterface(code, p), true)
@ -2711,7 +2710,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt
b = append(b, '{') b = append(b, '{')
} }
b = append(b, code.EscapedKey...) b = append(b, code.EscapedKey...)
if code.Type.Kind() == reflect.Ptr { if code.IsNilableType {
if code.Indirect || code.Op == encoder.OpStructPtrHeadMarshalJSON { if code.Indirect || code.Op == encoder.OpStructPtrHeadMarshalJSON {
p = ptrToPtr(p + code.Offset) p = ptrToPtr(p + code.Offset)
} }
@ -2755,7 +2754,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt
b = append(b, '{') b = append(b, '{')
} }
b = append(b, code.EscapedKey...) b = append(b, code.EscapedKey...)
if code.Type.Kind() == reflect.Ptr { if code.IsNilableType {
if code.Indirect || code.Op == encoder.OpStructPtrHeadStringTagMarshalJSON { if code.Indirect || code.Op == encoder.OpStructPtrHeadStringTagMarshalJSON {
p = ptrToPtr(p + code.Offset) p = ptrToPtr(p + code.Offset)
} }
@ -2798,7 +2797,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt
if !code.AnonymousHead { if !code.AnonymousHead {
b = append(b, '{') b = append(b, '{')
} }
if code.Type.Kind() == reflect.Ptr { if code.IsNilableType {
if code.Indirect || code.Op == encoder.OpStructPtrHeadOmitEmptyMarshalJSON { if code.Indirect || code.Op == encoder.OpStructPtrHeadOmitEmptyMarshalJSON {
p = ptrToPtr(p + code.Offset) p = ptrToPtr(p + code.Offset)
} }
@ -2924,7 +2923,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt
b = append(b, '{') b = append(b, '{')
} }
b = append(b, code.EscapedKey...) b = append(b, code.EscapedKey...)
if code.Type.Kind() == reflect.Ptr { if code.IsNilableType {
if code.Indirect || code.Op == encoder.OpStructPtrHeadMarshalText { if code.Indirect || code.Op == encoder.OpStructPtrHeadMarshalText {
p = ptrToPtr(p + code.Offset) p = ptrToPtr(p + code.Offset)
} }
@ -2968,7 +2967,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt
b = append(b, '{') b = append(b, '{')
} }
b = append(b, code.EscapedKey...) b = append(b, code.EscapedKey...)
if code.Type.Kind() == reflect.Ptr { if code.IsNilableType {
if code.Indirect || code.Op == encoder.OpStructPtrHeadStringTagMarshalText { if code.Indirect || code.Op == encoder.OpStructPtrHeadStringTagMarshalText {
p = ptrToPtr(p + code.Offset) p = ptrToPtr(p + code.Offset)
} }
@ -3011,7 +3010,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt
if !code.AnonymousHead { if !code.AnonymousHead {
b = append(b, '{') b = append(b, '{')
} }
if code.Type.Kind() == reflect.Ptr { if code.IsNilableType {
if code.Indirect || code.Op == encoder.OpStructPtrHeadOmitEmptyMarshalText { if code.Indirect || code.Op == encoder.OpStructPtrHeadOmitEmptyMarshalText {
p = ptrToPtr(p + code.Offset) p = ptrToPtr(p + code.Offset)
} }
@ -3623,7 +3622,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt
p := load(ctxptr, code.HeadIdx) p := load(ctxptr, code.HeadIdx)
b = append(b, code.EscapedKey...) b = append(b, code.EscapedKey...)
p += code.Offset p += code.Offset
if code.Type.Kind() == reflect.Ptr { if code.IsNilableType {
p = ptrToPtr(p) p = ptrToPtr(p)
} }
if p == 0 && code.Nilcheck { if p == 0 && code.Nilcheck {
@ -3640,7 +3639,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt
case encoder.OpStructFieldOmitEmptyMarshalJSON: case encoder.OpStructFieldOmitEmptyMarshalJSON:
p := load(ctxptr, code.HeadIdx) p := load(ctxptr, code.HeadIdx)
p += code.Offset p += code.Offset
if code.Type.Kind() == reflect.Ptr { if code.IsNilableType {
p = ptrToPtr(p) p = ptrToPtr(p)
} }
if p == 0 && code.Nilcheck { if p == 0 && code.Nilcheck {
@ -3685,7 +3684,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt
p := load(ctxptr, code.HeadIdx) p := load(ctxptr, code.HeadIdx)
b = append(b, code.EscapedKey...) b = append(b, code.EscapedKey...)
p += code.Offset p += code.Offset
if code.Type.Kind() == reflect.Ptr { if code.IsNilableType {
p = ptrToPtr(p) p = ptrToPtr(p)
} }
if p == 0 && code.Nilcheck { if p == 0 && code.Nilcheck {
@ -3702,7 +3701,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt
case encoder.OpStructFieldOmitEmptyMarshalText: case encoder.OpStructFieldOmitEmptyMarshalText:
p := load(ctxptr, code.HeadIdx) p := load(ctxptr, code.HeadIdx)
p += code.Offset p += code.Offset
if code.Type.Kind() == reflect.Ptr { if code.IsNilableType {
p = ptrToPtr(p) p = ptrToPtr(p)
} }
if p == 0 && code.Nilcheck { if p == 0 && code.Nilcheck {

View File

@ -4,7 +4,6 @@ import (
"bytes" "bytes"
"fmt" "fmt"
"math" "math"
"reflect"
"sort" "sort"
"unsafe" "unsafe"
@ -269,7 +268,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt
code = code.Next code = code.Next
break break
} }
if code.Type.Kind() == reflect.Ptr && code.Indirect { if code.IsNilableType && code.Indirect {
p = ptrToPtr(p) p = ptrToPtr(p)
} }
bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p), code.Indent, true) bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p), code.Indent, true)
@ -296,7 +295,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt
code = code.Next code = code.Next
break break
} }
if code.Type.Kind() == reflect.Ptr && code.Indirect { if code.IsNilableType && code.Indirect {
p = ptrToPtr(p) p = ptrToPtr(p)
} }
bb, err := appendMarshalText(code, b, ptrToInterface(code, p), true) bb, err := appendMarshalText(code, b, ptrToInterface(code, p), true)
@ -2844,7 +2843,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt
b = appendIndent(ctx, b, code.Indent+1) b = appendIndent(ctx, b, code.Indent+1)
b = append(b, code.EscapedKey...) b = append(b, code.EscapedKey...)
b = append(b, ' ') b = append(b, ' ')
if code.Type.Kind() == reflect.Ptr { if code.IsNilableType {
if code.Indirect || code.Op == encoder.OpStructPtrHeadMarshalJSON { if code.Indirect || code.Op == encoder.OpStructPtrHeadMarshalJSON {
p = ptrToPtr(p + code.Offset) p = ptrToPtr(p + code.Offset)
} }
@ -2890,7 +2889,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt
b = appendIndent(ctx, b, code.Indent+1) b = appendIndent(ctx, b, code.Indent+1)
b = append(b, code.EscapedKey...) b = append(b, code.EscapedKey...)
b = append(b, ' ') b = append(b, ' ')
if code.Type.Kind() == reflect.Ptr { if code.IsNilableType {
if code.Indirect || code.Op == encoder.OpStructPtrHeadStringTagMarshalJSON { if code.Indirect || code.Op == encoder.OpStructPtrHeadStringTagMarshalJSON {
p = ptrToPtr(p + code.Offset) p = ptrToPtr(p + code.Offset)
} }
@ -2933,7 +2932,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt
if !code.AnonymousHead { if !code.AnonymousHead {
b = append(b, '{', '\n') b = append(b, '{', '\n')
} }
if code.Type.Kind() == reflect.Ptr { if code.IsNilableType {
if code.Indirect || code.Op == encoder.OpStructPtrHeadOmitEmptyMarshalJSON { if code.Indirect || code.Op == encoder.OpStructPtrHeadOmitEmptyMarshalJSON {
p = ptrToPtr(p + code.Offset) p = ptrToPtr(p + code.Offset)
} }
@ -3067,7 +3066,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt
b = appendIndent(ctx, b, code.Indent+1) b = appendIndent(ctx, b, code.Indent+1)
b = append(b, code.EscapedKey...) b = append(b, code.EscapedKey...)
b = append(b, ' ') b = append(b, ' ')
if code.Type.Kind() == reflect.Ptr { if code.IsNilableType {
if code.Indirect || code.Op == encoder.OpStructPtrHeadMarshalText { if code.Indirect || code.Op == encoder.OpStructPtrHeadMarshalText {
p = ptrToPtr(p + code.Offset) p = ptrToPtr(p + code.Offset)
} }
@ -3113,7 +3112,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt
b = appendIndent(ctx, b, code.Indent+1) b = appendIndent(ctx, b, code.Indent+1)
b = append(b, code.EscapedKey...) b = append(b, code.EscapedKey...)
b = append(b, ' ') b = append(b, ' ')
if code.Type.Kind() == reflect.Ptr { if code.IsNilableType {
if code.Indirect || code.Op == encoder.OpStructPtrHeadStringTagMarshalText { if code.Indirect || code.Op == encoder.OpStructPtrHeadStringTagMarshalText {
p = ptrToPtr(p + code.Offset) p = ptrToPtr(p + code.Offset)
} }
@ -3156,7 +3155,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt
if !code.AnonymousHead { if !code.AnonymousHead {
b = append(b, '{', '\n') b = append(b, '{', '\n')
} }
if code.Type.Kind() == reflect.Ptr { if code.IsNilableType {
if code.Indirect || code.Op == encoder.OpStructPtrHeadOmitEmptyMarshalText { if code.Indirect || code.Op == encoder.OpStructPtrHeadOmitEmptyMarshalText {
p = ptrToPtr(p + code.Offset) p = ptrToPtr(p + code.Offset)
} }
@ -3870,7 +3869,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt
b = append(b, ' ') b = append(b, ' ')
p := load(ctxptr, code.HeadIdx) p := load(ctxptr, code.HeadIdx)
p += code.Offset p += code.Offset
if code.Type.Kind() == reflect.Ptr { if code.IsNilableType {
p = ptrToPtr(p) p = ptrToPtr(p)
} }
if p == 0 && code.Nilcheck { if p == 0 && code.Nilcheck {
@ -3887,7 +3886,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt
case encoder.OpStructFieldOmitEmptyMarshalJSON: case encoder.OpStructFieldOmitEmptyMarshalJSON:
p := load(ctxptr, code.HeadIdx) p := load(ctxptr, code.HeadIdx)
p += code.Offset p += code.Offset
if code.Type.Kind() == reflect.Ptr { if code.IsNilableType {
p = ptrToPtr(p) p = ptrToPtr(p)
} }
if p == 0 && code.Nilcheck { if p == 0 && code.Nilcheck {
@ -3940,7 +3939,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt
b = append(b, code.EscapedKey...) b = append(b, code.EscapedKey...)
b = append(b, ' ') b = append(b, ' ')
p += code.Offset p += code.Offset
if code.Type.Kind() == reflect.Ptr { if code.IsNilableType {
p = ptrToPtr(p) p = ptrToPtr(p)
} }
if p == 0 && code.Nilcheck { if p == 0 && code.Nilcheck {
@ -3957,7 +3956,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt
case encoder.OpStructFieldOmitEmptyMarshalText: case encoder.OpStructFieldOmitEmptyMarshalText:
p := load(ctxptr, code.HeadIdx) p := load(ctxptr, code.HeadIdx)
p += code.Offset p += code.Offset
if code.Type.Kind() == reflect.Ptr { if code.IsNilableType {
p = ptrToPtr(p) p = ptrToPtr(p)
} }
if p == 0 && code.Nilcheck { if p == 0 && code.Nilcheck {

View File

@ -4,7 +4,6 @@ import (
"bytes" "bytes"
"fmt" "fmt"
"math" "math"
"reflect"
"sort" "sort"
"unsafe" "unsafe"
@ -275,7 +274,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt
code = code.Next code = code.Next
break break
} }
if code.Type.Kind() == reflect.Ptr && code.Indirect { if code.IsNilableType && code.Indirect {
p = ptrToPtr(p) p = ptrToPtr(p)
} }
bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p), code.Indent, false) bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p), code.Indent, false)
@ -302,7 +301,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt
code = code.Next code = code.Next
break break
} }
if code.Type.Kind() == reflect.Ptr && code.Indirect { if code.IsNilableType && code.Indirect {
p = ptrToPtr(p) p = ptrToPtr(p)
} }
bb, err := appendMarshalText(code, b, ptrToInterface(code, p), false) bb, err := appendMarshalText(code, b, ptrToInterface(code, p), false)
@ -2850,7 +2849,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt
b = appendIndent(ctx, b, code.Indent+1) b = appendIndent(ctx, b, code.Indent+1)
b = append(b, code.Key...) b = append(b, code.Key...)
b = append(b, ' ') b = append(b, ' ')
if code.Type.Kind() == reflect.Ptr { if code.IsNilableType {
if code.Indirect || code.Op == encoder.OpStructPtrHeadMarshalJSON { if code.Indirect || code.Op == encoder.OpStructPtrHeadMarshalJSON {
p = ptrToPtr(p + code.Offset) p = ptrToPtr(p + code.Offset)
} }
@ -2896,7 +2895,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt
b = appendIndent(ctx, b, code.Indent+1) b = appendIndent(ctx, b, code.Indent+1)
b = append(b, code.Key...) b = append(b, code.Key...)
b = append(b, ' ') b = append(b, ' ')
if code.Type.Kind() == reflect.Ptr { if code.IsNilableType {
if code.Indirect || code.Op == encoder.OpStructPtrHeadStringTagMarshalJSON { if code.Indirect || code.Op == encoder.OpStructPtrHeadStringTagMarshalJSON {
p = ptrToPtr(p + code.Offset) p = ptrToPtr(p + code.Offset)
} }
@ -2939,7 +2938,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt
if !code.AnonymousHead { if !code.AnonymousHead {
b = append(b, '{', '\n') b = append(b, '{', '\n')
} }
if code.Type.Kind() == reflect.Ptr { if code.IsNilableType {
if code.Indirect || code.Op == encoder.OpStructPtrHeadOmitEmptyMarshalJSON { if code.Indirect || code.Op == encoder.OpStructPtrHeadOmitEmptyMarshalJSON {
p = ptrToPtr(p + code.Offset) p = ptrToPtr(p + code.Offset)
} }
@ -3073,7 +3072,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt
b = appendIndent(ctx, b, code.Indent+1) b = appendIndent(ctx, b, code.Indent+1)
b = append(b, code.Key...) b = append(b, code.Key...)
b = append(b, ' ') b = append(b, ' ')
if code.Type.Kind() == reflect.Ptr { if code.IsNilableType {
if code.Indirect || code.Op == encoder.OpStructPtrHeadMarshalText { if code.Indirect || code.Op == encoder.OpStructPtrHeadMarshalText {
p = ptrToPtr(p + code.Offset) p = ptrToPtr(p + code.Offset)
} }
@ -3119,7 +3118,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt
b = appendIndent(ctx, b, code.Indent+1) b = appendIndent(ctx, b, code.Indent+1)
b = append(b, code.Key...) b = append(b, code.Key...)
b = append(b, ' ') b = append(b, ' ')
if code.Type.Kind() == reflect.Ptr { if code.IsNilableType {
if code.Indirect || code.Op == encoder.OpStructPtrHeadStringTagMarshalText { if code.Indirect || code.Op == encoder.OpStructPtrHeadStringTagMarshalText {
p = ptrToPtr(p + code.Offset) p = ptrToPtr(p + code.Offset)
} }
@ -3162,7 +3161,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt
if !code.AnonymousHead { if !code.AnonymousHead {
b = append(b, '{', '\n') b = append(b, '{', '\n')
} }
if code.Type.Kind() == reflect.Ptr { if code.IsNilableType {
if code.Indirect || code.Op == encoder.OpStructPtrHeadOmitEmptyMarshalText { if code.Indirect || code.Op == encoder.OpStructPtrHeadOmitEmptyMarshalText {
p = ptrToPtr(p + code.Offset) p = ptrToPtr(p + code.Offset)
} }
@ -3876,7 +3875,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt
b = append(b, ' ') b = append(b, ' ')
p := load(ctxptr, code.HeadIdx) p := load(ctxptr, code.HeadIdx)
p += code.Offset p += code.Offset
if code.Type.Kind() == reflect.Ptr { if code.IsNilableType {
p = ptrToPtr(p) p = ptrToPtr(p)
} }
if p == 0 && code.Nilcheck { if p == 0 && code.Nilcheck {
@ -3893,7 +3892,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt
case encoder.OpStructFieldOmitEmptyMarshalJSON: case encoder.OpStructFieldOmitEmptyMarshalJSON:
p := load(ctxptr, code.HeadIdx) p := load(ctxptr, code.HeadIdx)
p += code.Offset p += code.Offset
if code.Type.Kind() == reflect.Ptr { if code.IsNilableType {
p = ptrToPtr(p) p = ptrToPtr(p)
} }
if p == 0 && code.Nilcheck { if p == 0 && code.Nilcheck {
@ -3946,7 +3945,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt
b = append(b, code.Key...) b = append(b, code.Key...)
b = append(b, ' ') b = append(b, ' ')
p += code.Offset p += code.Offset
if code.Type.Kind() == reflect.Ptr { if code.IsNilableType {
p = ptrToPtr(p) p = ptrToPtr(p)
} }
if p == 0 && code.Nilcheck { if p == 0 && code.Nilcheck {
@ -3963,7 +3962,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt
case encoder.OpStructFieldOmitEmptyMarshalText: case encoder.OpStructFieldOmitEmptyMarshalText:
p := load(ctxptr, code.HeadIdx) p := load(ctxptr, code.HeadIdx)
p += code.Offset p += code.Offset
if code.Type.Kind() == reflect.Ptr { if code.IsNilableType {
p = ptrToPtr(p) p = ptrToPtr(p)
} }
if p == 0 && code.Nilcheck { if p == 0 && code.Nilcheck {