From ee52d7f0aefcff5b56befff412b8227e85d092d1 Mon Sep 17 00:00:00 2001 From: Masaaki Goshima Date: Mon, 7 Dec 2020 10:44:24 +0900 Subject: [PATCH] Fix double pointer --- decode_compile.go | 8 -------- decode_unmarshal_json.go | 28 ++++++++------------------- decode_unmarshal_text.go | 4 +--- encode_test.go | 2 +- encode_vm.go | 42 ++++++++++++++-------------------------- 5 files changed, 25 insertions(+), 59 deletions(-) diff --git a/decode_compile.go b/decode_compile.go index 8d92f5d..1061e85 100644 --- a/decode_compile.go +++ b/decode_compile.go @@ -8,12 +8,8 @@ import ( func (d *Decoder) compileHead(typ *rtype) (decoder, error) { switch { - case typ.Implements(unmarshalJSONType): - return newUnmarshalJSONDecoder(typ, "", ""), nil case rtype_ptrTo(typ).Implements(unmarshalJSONType): return newUnmarshalJSONDecoder(rtype_ptrTo(typ), "", ""), nil - case typ.Implements(unmarshalTextType): - return newUnmarshalTextDecoder(typ, "", ""), nil case rtype_ptrTo(typ).Implements(unmarshalTextType): return newUnmarshalTextDecoder(rtype_ptrTo(typ), "", ""), nil } @@ -22,12 +18,8 @@ func (d *Decoder) compileHead(typ *rtype) (decoder, error) { func (d *Decoder) compile(typ *rtype, structName, fieldName string) (decoder, error) { switch { - case typ.Implements(unmarshalJSONType): - return newUnmarshalJSONDecoder(typ, structName, fieldName), nil case rtype_ptrTo(typ).Implements(unmarshalJSONType): return newUnmarshalJSONDecoder(rtype_ptrTo(typ), structName, fieldName), nil - case typ.Implements(unmarshalTextType): - return newUnmarshalTextDecoder(typ, structName, fieldName), nil case rtype_ptrTo(typ).Implements(unmarshalTextType): return newUnmarshalTextDecoder(rtype_ptrTo(typ), structName, fieldName), nil } diff --git a/decode_unmarshal_json.go b/decode_unmarshal_json.go index d951e75..2674a07 100644 --- a/decode_unmarshal_json.go +++ b/decode_unmarshal_json.go @@ -38,26 +38,14 @@ func (d *unmarshalJSONDecoder) decodeStream(s *stream, p unsafe.Pointer) error { src := s.buf[start:s.cursor] dst := make([]byte, len(src)) copy(dst, src) - if d.isDoublePointer { - newptr := unsafe_New(d.typ.Elem()) - v := *(*interface{})(unsafe.Pointer(&interfaceHeader{ - typ: d.typ, - ptr: newptr, - })) - if err := v.(Unmarshaler).UnmarshalJSON(dst); err != nil { - d.annotateError(s.cursor, err) - return err - } - *(*unsafe.Pointer)(p) = newptr - } else { - v := *(*interface{})(unsafe.Pointer(&interfaceHeader{ - typ: d.typ, - ptr: p, - })) - if err := v.(Unmarshaler).UnmarshalJSON(dst); err != nil { - d.annotateError(s.cursor, err) - return err - } + + v := *(*interface{})(unsafe.Pointer(&interfaceHeader{ + typ: d.typ, + ptr: p, + })) + if err := v.(Unmarshaler).UnmarshalJSON(dst); err != nil { + d.annotateError(s.cursor, err) + return err } return nil } diff --git a/decode_unmarshal_text.go b/decode_unmarshal_text.go index 170f95a..26b28ec 100644 --- a/decode_unmarshal_text.go +++ b/decode_unmarshal_text.go @@ -45,16 +45,14 @@ func (d *unmarshalTextDecoder) decodeStream(s *stream, p unsafe.Pointer) error { if b, ok := unquoteBytes(dst); ok { dst = b } - newptr := unsafe_New(d.typ.Elem()) v := *(*interface{})(unsafe.Pointer(&interfaceHeader{ typ: d.typ, - ptr: newptr, + ptr: p, })) if err := v.(encoding.TextUnmarshaler).UnmarshalText(dst); err != nil { d.annotateError(s.cursor, err) return err } - *(*unsafe.Pointer)(p) = newptr return nil } diff --git a/encode_test.go b/encode_test.go index 316e3c6..fa3f21f 100644 --- a/encode_test.go +++ b/encode_test.go @@ -1298,7 +1298,7 @@ func TestNilMarshal(t *testing.T) { {v: struct{ M string }{"gopher"}, want: `{"M":"gopher"}`}, {v: struct{ M json.Marshaler }{}, want: `{"M":null}`}, {v: struct{ M json.Marshaler }{(*nilJSONMarshaler)(nil)}, want: `{"M":"0zenil0"}`}, - {v: struct{ M interface{} }{(*nilJSONMarshaler)(nil)}, want: `{"M":"0zenil0"}`}, // doesn't compatible with encoding/json + {v: struct{ M interface{} }{(*nilJSONMarshaler)(nil)}, want: `{"M":null}`}, {v: struct{ M encoding.TextMarshaler }{}, want: `{"M":null}`}, {v: struct{ M encoding.TextMarshaler }{(*nilTextMarshaler)(nil)}, want: `{"M":"0zenil0"}`}, {v: struct{ M interface{} }{(*nilTextMarshaler)(nil)}, want: `{"M":null}`}, diff --git a/encode_vm.go b/encode_vm.go index 2a83ca0..a3b5768 100644 --- a/encode_vm.go +++ b/encode_vm.go @@ -226,35 +226,23 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { } vv := rv.Interface() header := (*interfaceHeader)(unsafe.Pointer(&vv)) - typ := header.typ - if typ.Kind() == reflect.Ptr { - typ = typ.Elem() - } - var c *opcode - if typ.Kind() == reflect.Map { - code, err := e.compileMap(&encodeCompileContext{ - typ: typ, - root: code.root, - withIndent: e.enabledIndent, - indent: code.indent, - }, false) - if err != nil { - return err + if header.typ.Kind() == reflect.Ptr { + if rv.Elem().IsNil() { + e.encodeNull() + e.encodeByte(',') + code = code.next + break } - c = code - } else { - code, err := e.compile(&encodeCompileContext{ - typ: typ, - root: code.root, - withIndent: e.enabledIndent, - indent: code.indent, - }) - if err != nil { - return err - } - c = code } - + c, err := e.compileHead(&encodeCompileContext{ + typ: header.typ, + root: code.root, + withIndent: e.enabledIndent, + indent: code.indent, + }) + if err != nil { + return err + } beforeLastCode := c.beforeLastCode() lastCode := beforeLastCode.next lastCode.idx = beforeLastCode.idx + uintptrSize