ugorji / go

idiomatic codec and rpc lib for msgpack, cbor, json, etc. msgpack.org[Go]
MIT License
1.85k stars 295 forks source link

How to define extension to Pointer Type #322

Closed rucciva closed 4 years ago

rucciva commented 4 years ago

how to decode-back pointer of custom type into nil interface?

I've tried with the following code:

package regexp

import (
    "reflect"
    "testing"

    "github.com/ugorji/go/codec"
)

type MyType struct {
    A string
}

type MyTypeList struct {
    L []interface{}
}

type MyTypeExt struct{}

func (x MyTypeExt) WriteExt(v interface{}) []byte {
    v2 := v.(*MyType) // structs are encoded by passing the ptr
    return []byte(v2.A)
}
func (x MyTypeExt) ReadExt(dest interface{}, v []byte) {
    tt := dest.(*MyType)
    tt.A = string(v)
}

func TestBinc(t *testing.T) {
    mt := &MyType{"test"}
    a := MyTypeList{[]interface{}{mt}}

    var bh codec.BincHandle

    bh.SetBytesExt(reflect.TypeOf(MyType{}), 1, MyTypeExt{})
    var w []byte
    enc := codec.NewEncoderBytes(&w, &bh)
    if err := enc.Encode(a); err != nil {
        t.Fatal(err)
    }

    b := MyTypeList{}
    dec := codec.NewDecoderBytes(w, &bh)
    if err := dec.Decode(&b); err != nil {
        t.Error(err)
    }
    if _, ok := b.L[0].(*MyType); !ok {
        t.Fatalf("decoded type : %T\n", b.L[0])
    }

}

which result in:

--- FAIL: TestBinc (0.00s)
    /***/binc_test.go:48: decoded type : regexp.MyType
ugorji commented 4 years ago

This is hard to do now, due to backward compatibility. There are likely folks who have assumed that a non-pointer will be decoded into a nil interface{}.

We need to introduce a flag to support this.