github.com/anthdm/go-ethereum@v1.8.4-0.20180412101906-60516c83b011/accounts/abi/reflect.go (about)

     1  // Copyright 2016 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package abi
    18  
    19  import (
    20  	"fmt"
    21  	"reflect"
    22  )
    23  
    24  // indirect recursively dereferences the value until it either gets the value
    25  // or finds a big.Int
    26  func indirect(v reflect.Value) reflect.Value {
    27  	if v.Kind() == reflect.Ptr && v.Elem().Type() != derefbigT {
    28  		return indirect(v.Elem())
    29  	}
    30  	return v
    31  }
    32  
    33  // reflectIntKind returns the reflect using the given size and
    34  // unsignedness.
    35  func reflectIntKindAndType(unsigned bool, size int) (reflect.Kind, reflect.Type) {
    36  	switch size {
    37  	case 8:
    38  		if unsigned {
    39  			return reflect.Uint8, uint8T
    40  		}
    41  		return reflect.Int8, int8T
    42  	case 16:
    43  		if unsigned {
    44  			return reflect.Uint16, uint16T
    45  		}
    46  		return reflect.Int16, int16T
    47  	case 32:
    48  		if unsigned {
    49  			return reflect.Uint32, uint32T
    50  		}
    51  		return reflect.Int32, int32T
    52  	case 64:
    53  		if unsigned {
    54  			return reflect.Uint64, uint64T
    55  		}
    56  		return reflect.Int64, int64T
    57  	}
    58  	return reflect.Ptr, bigT
    59  }
    60  
    61  // mustArrayToBytesSlice creates a new byte slice with the exact same size as value
    62  // and copies the bytes in value to the new slice.
    63  func mustArrayToByteSlice(value reflect.Value) reflect.Value {
    64  	slice := reflect.MakeSlice(reflect.TypeOf([]byte{}), value.Len(), value.Len())
    65  	reflect.Copy(slice, value)
    66  	return slice
    67  }
    68  
    69  // set attempts to assign src to dst by either setting, copying or otherwise.
    70  //
    71  // set is a bit more lenient when it comes to assignment and doesn't force an as
    72  // strict ruleset as bare `reflect` does.
    73  func set(dst, src reflect.Value, output Argument) error {
    74  	dstType := dst.Type()
    75  	srcType := src.Type()
    76  	switch {
    77  	case dstType.AssignableTo(srcType):
    78  		dst.Set(src)
    79  	case dstType.Kind() == reflect.Interface:
    80  		dst.Set(src)
    81  	case dstType.Kind() == reflect.Ptr:
    82  		return set(dst.Elem(), src, output)
    83  	default:
    84  		return fmt.Errorf("abi: cannot unmarshal %v in to %v", src.Type(), dst.Type())
    85  	}
    86  	return nil
    87  }
    88  
    89  // requireAssignable assures that `dest` is a pointer and it's not an interface.
    90  func requireAssignable(dst, src reflect.Value) error {
    91  	if dst.Kind() != reflect.Ptr && dst.Kind() != reflect.Interface {
    92  		return fmt.Errorf("abi: cannot unmarshal %v into %v", src.Type(), dst.Type())
    93  	}
    94  	return nil
    95  }
    96  
    97  // requireUnpackKind verifies preconditions for unpacking `args` into `kind`
    98  func requireUnpackKind(v reflect.Value, t reflect.Type, k reflect.Kind,
    99  	args Arguments) error {
   100  
   101  	switch k {
   102  	case reflect.Struct:
   103  	case reflect.Slice, reflect.Array:
   104  		if minLen := args.LengthNonIndexed(); v.Len() < minLen {
   105  			return fmt.Errorf("abi: insufficient number of elements in the list/array for unpack, want %d, got %d",
   106  				minLen, v.Len())
   107  		}
   108  	default:
   109  		return fmt.Errorf("abi: cannot unmarshal tuple into %v", t)
   110  	}
   111  	return nil
   112  }
   113  
   114  // requireUniqueStructFieldNames makes sure field names don't collide
   115  func requireUniqueStructFieldNames(args Arguments) error {
   116  	exists := make(map[string]bool)
   117  	for _, arg := range args {
   118  		field := capitalise(arg.Name)
   119  		if field == "" {
   120  			return fmt.Errorf("abi: purely underscored output cannot unpack to struct")
   121  		}
   122  		if exists[field] {
   123  			return fmt.Errorf("abi: multiple outputs mapping to the same struct field '%s'", field)
   124  		}
   125  		exists[field] = true
   126  	}
   127  	return nil
   128  }