@@ -84,12 +84,7 @@ func (d *decoder) sizeFromCtrlByte(ctrlByte byte, offset uint, typeNum dataType)
84
84
}
85
85
86
86
func (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 )
93
88
94
89
switch dtype {
95
90
case _Bool :
@@ -143,6 +138,23 @@ func (d *decoder) unmarshalBool(size uint, offset uint, result reflect.Value) (u
143
138
}
144
139
}
145
140
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
+
146
158
func (d * decoder ) unmarshalBytes (size uint , offset uint , result reflect.Value ) (uint , error ) {
147
159
value , newOffset , err := d .decodeBytes (size , offset )
148
160
if err != nil {
@@ -238,6 +250,7 @@ func (d *decoder) unmarshalInt32(size uint, offset uint, result reflect.Value) (
238
250
}
239
251
240
252
func (d * decoder ) unmarshalMap (size uint , offset uint , result reflect.Value ) (uint , error ) {
253
+ result = d .indirect (result )
241
254
switch result .Kind () {
242
255
default :
243
256
return 0 , newUnmarshalTypeError ("map" , result .Type ())
@@ -250,17 +263,6 @@ func (d *decoder) unmarshalMap(size uint, offset uint, result reflect.Value) (ui
250
263
newOffset , err := d .decodeMap (size , offset , rv )
251
264
result .Set (rv )
252
265
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 )
264
266
}
265
267
}
266
268
0 commit comments