diff --git a/allocator.go b/allocator.go new file mode 100644 index 0000000..213dce7 --- /dev/null +++ b/allocator.go @@ -0,0 +1,27 @@ +package ssob + +import ( + "errors" + "reflect" +) + +func allocType(out reflect.Value) (err error) { + if out.Type().Kind() != reflect.Ptr || out.IsNil() { + return errors.New("ssob: Error allocating type (Got nil pointer)") + } + + t := out.Elem().Type() + ret := reflect.New(t) + retp := ret + for { + if reflect.Ptr != t.Kind() { + break + } + retp = retp.Elem() + t = retp.Type().Elem() + retp.Set(reflect.New(t)) + } + out.Elem().Set(reflect.Indirect(ret)) + + return nil +} diff --git a/unmarshal.go b/unmarshal.go index c55b024..d4eb90a 100644 --- a/unmarshal.go +++ b/unmarshal.go @@ -573,8 +573,15 @@ func unmarshal(e interface{}, in []byte) (n int, err error) { return unmarshal(e, in) } } + if !p.Elem().IsValid() { + err = allocType(v) + if err != nil { + return 0, err + } + p = reflect.Indirect(v) + } - return unmarshal(p, in) + return unmarshal(p.Interface(), in) } func RegisterDecoder(name string, f func(e interface{}, in []byte) (n int, err error)) { diff --git a/unsafe_unmarshal.go b/unsafe_unmarshal.go index 51a7be6..dcd5c0d 100644 --- a/unsafe_unmarshal.go +++ b/unsafe_unmarshal.go @@ -700,8 +700,15 @@ func unsafeUnmarshal(e interface{}, in []byte) (n int, err error) { return unsafeUnmarshal(e, in) } } + if !p.Elem().IsValid() { + err = allocType(v) + if err != nil { + return 0, err + } + p = reflect.Indirect(v) + } - return unsafeUnmarshal(p, in) + return unsafeUnmarshal(p.Interface(), in) } func RegisterUnsafeDecoder(name string, f func(e interface{}, in []byte) (n int, err error)) {