@@ -238,8 +238,16 @@ func (abi ABI) Unpack(v interface{}, name string, output []byte) error {
238
238
return fmt .Errorf ("abi: unmarshalling empty output" )
239
239
}
240
240
241
- value := reflect .ValueOf (v ).Elem ()
242
- typ := value .Type ()
241
+ // make sure the passed value is a pointer
242
+ valueOf := reflect .ValueOf (v )
243
+ if reflect .Ptr != valueOf .Kind () {
244
+ return fmt .Errorf ("abi: Unpack(non-pointer %T)" , v )
245
+ }
246
+
247
+ var (
248
+ value = valueOf .Elem ()
249
+ typ = value .Type ()
250
+ )
243
251
244
252
if len (method .Outputs ) > 1 {
245
253
switch value .Kind () {
@@ -268,6 +276,25 @@ func (abi ABI) Unpack(v interface{}, name string, output []byte) error {
268
276
return fmt .Errorf ("abi: cannot marshal tuple in to slice %T (only []interface{} is supported)" , v )
269
277
}
270
278
279
+ // if the slice already contains values, set those instead of the interface slice itself.
280
+ if value .Len () > 0 {
281
+ if len (method .Outputs ) > value .Len () {
282
+ return fmt .Errorf ("abi: cannot marshal in to slices of unequal size (require: %v, got: %v)" , len (method .Outputs ), value .Len ())
283
+ }
284
+
285
+ for i := 0 ; i < len (method .Outputs ); i ++ {
286
+ marshalledValue , err := toGoType (i , method .Outputs [i ], output )
287
+ if err != nil {
288
+ return err
289
+ }
290
+ reflectValue := reflect .ValueOf (marshalledValue )
291
+ if err := set (value .Index (i ).Elem (), reflectValue , method .Outputs [i ]); err != nil {
292
+ return err
293
+ }
294
+ }
295
+ return nil
296
+ }
297
+
271
298
// create a new slice and start appending the unmarshalled
272
299
// values to the new interface slice.
273
300
z := reflect .MakeSlice (typ , 0 , len (method .Outputs ))
@@ -296,34 +323,6 @@ func (abi ABI) Unpack(v interface{}, name string, output []byte) error {
296
323
return nil
297
324
}
298
325
299
- // set attempts to assign src to dst by either setting, copying or otherwise.
300
- //
301
- // set is a bit more lenient when it comes to assignment and doesn't force an as
302
- // strict ruleset as bare `reflect` does.
303
- func set (dst , src reflect.Value , output Argument ) error {
304
- dstType := dst .Type ()
305
- srcType := src .Type ()
306
-
307
- switch {
308
- case dstType .AssignableTo (src .Type ()):
309
- dst .Set (src )
310
- case dstType .Kind () == reflect .Array && srcType .Kind () == reflect .Slice :
311
- if ! dstType .Elem ().AssignableTo (r_byte ) {
312
- return fmt .Errorf ("abi: cannot unmarshal %v in to array of elem %v" , src .Type (), dstType .Elem ())
313
- }
314
-
315
- if dst .Len () < output .Type .SliceSize {
316
- return fmt .Errorf ("abi: cannot unmarshal src (len=%d) in to dst (len=%d)" , output .Type .SliceSize , dst .Len ())
317
- }
318
- reflect .Copy (dst , src )
319
- case dstType .Kind () == reflect .Interface :
320
- dst .Set (src )
321
- default :
322
- return fmt .Errorf ("abi: cannot unmarshal %v in to %v" , src .Type (), dst .Type ())
323
- }
324
- return nil
325
- }
326
-
327
326
func (abi * ABI ) UnmarshalJSON (data []byte ) error {
328
327
var fields []struct {
329
328
Type string
0 commit comments