@@ -84,12 +84,7 @@ func (d *decoder) sizeFromCtrlByte(ctrlByte byte, offset uint, typeNum dataType)
8484}
8585
8686func (d * decoder ) decodeFromType (dtype dataType , size uint , offset uint , result reflect.Value ) (uint , error ) {
87- for result .Kind () == reflect .Ptr {
88- if result .IsNil () {
89- result .Set (reflect .New (result .Type ().Elem ()))
90- }
91- result = result .Elem ()
92- }
87+ result = d .indirect (result )
9388
9489 switch dtype {
9590 case _Bool :
@@ -143,6 +138,23 @@ func (d *decoder) unmarshalBool(size uint, offset uint, result reflect.Value) (u
143138 }
144139}
145140
141+ // follow pointers and create values as necessary
142+ func (d * decoder ) indirect (result reflect.Value ) reflect.Value {
143+ for {
144+ if result .Kind () == reflect .Ptr {
145+ if result .IsNil () {
146+ result .Set (reflect .New (result .Type ().Elem ()))
147+ }
148+ result = result .Elem ()
149+ } else if result .Kind () == reflect .Interface && ! result .IsNil () {
150+ result = result .Elem ()
151+ } else {
152+ break
153+ }
154+ }
155+ return result
156+ }
157+
146158func (d * decoder ) unmarshalBytes (size uint , offset uint , result reflect.Value ) (uint , error ) {
147159 value , newOffset , err := d .decodeBytes (size , offset )
148160 if err != nil {
@@ -238,6 +250,7 @@ func (d *decoder) unmarshalInt32(size uint, offset uint, result reflect.Value) (
238250}
239251
240252func (d * decoder ) unmarshalMap (size uint , offset uint , result reflect.Value ) (uint , error ) {
253+ result = d .indirect (result )
241254 switch result .Kind () {
242255 default :
243256 return 0 , newUnmarshalTypeError ("map" , result .Type ())
@@ -250,17 +263,6 @@ func (d *decoder) unmarshalMap(size uint, offset uint, result reflect.Value) (ui
250263 newOffset , err := d .decodeMap (size , offset , rv )
251264 result .Set (rv )
252265 return newOffset , err
253- case reflect .Ptr :
254- // XXX - This duplicate Ptr hanlding code exists because decodeMap
255- // calls unmarshalMap directly when handling embedded structs. It
256- // would be nice to clean this up.
257- for result .Kind () == reflect .Ptr {
258- if result .IsNil () {
259- result .Set (reflect .New (result .Type ().Elem ()))
260- }
261- result = result .Elem ()
262- }
263- return d .unmarshalMap (size , offset , result )
264266 }
265267}
266268
0 commit comments