github.com/arieschain/arieschain@v0.0.0-20191023063405-37c074544356/accounts/abi/reflect.go (about)

     1  package abi
     2  
     3  import (
     4  	"fmt"
     5  	"reflect"
     6  )
     7  
     8  // indirect recursively dereferences the value until it either gets the value
     9  // or finds a big.Int
    10  func indirect(v reflect.Value) reflect.Value {
    11  	if v.Kind() == reflect.Ptr && v.Elem().Type() != derefbigT {
    12  		return indirect(v.Elem())
    13  	}
    14  	return v
    15  }
    16  
    17  // reflectIntKind returns the reflect using the given size and
    18  // unsignedness.
    19  func reflectIntKindAndType(unsigned bool, size int) (reflect.Kind, reflect.Type) {
    20  	switch size {
    21  	case 8:
    22  		if unsigned {
    23  			return reflect.Uint8, uint8T
    24  		}
    25  		return reflect.Int8, int8T
    26  	case 16:
    27  		if unsigned {
    28  			return reflect.Uint16, uint16T
    29  		}
    30  		return reflect.Int16, int16T
    31  	case 32:
    32  		if unsigned {
    33  			return reflect.Uint32, uint32T
    34  		}
    35  		return reflect.Int32, int32T
    36  	case 64:
    37  		if unsigned {
    38  			return reflect.Uint64, uint64T
    39  		}
    40  		return reflect.Int64, int64T
    41  	}
    42  	return reflect.Ptr, bigT
    43  }
    44  
    45  // mustArrayToBytesSlice creates a new byte slice with the exact same size as value
    46  // and copies the bytes in value to the new slice.
    47  func mustArrayToByteSlice(value reflect.Value) reflect.Value {
    48  	slice := reflect.MakeSlice(reflect.TypeOf([]byte{}), value.Len(), value.Len())
    49  	reflect.Copy(slice, value)
    50  	return slice
    51  }
    52  
    53  // set attempts to assign src to dst by either setting, copying or otherwise.
    54  //
    55  // set is a bit more lenient when it comes to assignment and doesn't force an as
    56  // strict ruleset as bare `reflect` does.
    57  func set(dst, src reflect.Value, output Argument) error {
    58  	dstType := dst.Type()
    59  	srcType := src.Type()
    60  	switch {
    61  	case dstType.AssignableTo(srcType):
    62  		dst.Set(src)
    63  	case dstType.Kind() == reflect.Interface:
    64  		dst.Set(src)
    65  	case dstType.Kind() == reflect.Ptr:
    66  		return set(dst.Elem(), src, output)
    67  	default:
    68  		return fmt.Errorf("abi: cannot unmarshal %v in to %v", src.Type(), dst.Type())
    69  	}
    70  	return nil
    71  }
    72  
    73  // requireAssignable assures that `dest` is a pointer and it's not an interface.
    74  func requireAssignable(dst, src reflect.Value) error {
    75  	if dst.Kind() != reflect.Ptr && dst.Kind() != reflect.Interface {
    76  		return fmt.Errorf("abi: cannot unmarshal %v into %v", src.Type(), dst.Type())
    77  	}
    78  	return nil
    79  }
    80  
    81  // requireUnpackKind verifies preconditions for unpacking `args` into `kind`
    82  func requireUnpackKind(v reflect.Value, t reflect.Type, k reflect.Kind,
    83  	args Arguments) error {
    84  
    85  	switch k {
    86  	case reflect.Struct:
    87  	case reflect.Slice, reflect.Array:
    88  		if minLen := args.LengthNonIndexed(); v.Len() < minLen {
    89  			return fmt.Errorf("abi: insufficient number of elements in the list/array for unpack, want %d, got %d",
    90  				minLen, v.Len())
    91  		}
    92  	default:
    93  		return fmt.Errorf("abi: cannot unmarshal tuple into %v", t)
    94  	}
    95  	return nil
    96  }
    97  
    98  // requireUniqueStructFieldNames makes sure field names don't collide
    99  func requireUniqueStructFieldNames(args Arguments) error {
   100  	exists := make(map[string]bool)
   101  	for _, arg := range args {
   102  		field := capitalise(arg.Name)
   103  		if field == "" {
   104  			return fmt.Errorf("abi: purely underscored output cannot unpack to struct")
   105  		}
   106  		if exists[field] {
   107  			return fmt.Errorf("abi: multiple outputs mapping to the same struct field '%s'", field)
   108  		}
   109  		exists[field] = true
   110  	}
   111  	return nil
   112  }