Fix double pointer

This commit is contained in:
Masaaki Goshima 2020-12-07 10:44:24 +09:00
parent 5a8383f0d2
commit ee52d7f0ae
5 changed files with 25 additions and 59 deletions

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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}`},

View File

@ -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