github.com/simplechain-org/go-simplechain@v1.0.6/accounts/abi/pack.go (about)

     1  package abi
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"math/big"
     7  	"reflect"
     8  
     9  	"github.com/simplechain-org/go-simplechain/common"
    10  	"github.com/simplechain-org/go-simplechain/common/math"
    11  )
    12  
    13  // packBytesSlice packs the given bytes as [L, V] as the canonical representation
    14  // bytes slice.
    15  func packBytesSlice(bytes []byte, l int) []byte {
    16  	len := packNum(reflect.ValueOf(l))
    17  	return append(len, common.RightPadBytes(bytes, (l+31)/32*32)...)
    18  }
    19  
    20  // packElement packs the given reflect value according to the abi specification in
    21  // t.
    22  func packElement(t Type, reflectValue reflect.Value) ([]byte, error) {
    23  	switch t.T {
    24  	case IntTy, UintTy:
    25  		return packNum(reflectValue), nil
    26  	case StringTy:
    27  		return packBytesSlice([]byte(reflectValue.String()), reflectValue.Len()), nil
    28  	case AddressTy:
    29  		if reflectValue.Kind() == reflect.Array {
    30  			reflectValue = mustArrayToByteSlice(reflectValue)
    31  		}
    32  
    33  		return common.LeftPadBytes(reflectValue.Bytes(), 32), nil
    34  	case BoolTy:
    35  		if reflectValue.Bool() {
    36  			return math.PaddedBigBytes(common.Big1, 32), nil
    37  		}
    38  		return math.PaddedBigBytes(common.Big0, 32), nil
    39  	case BytesTy:
    40  		if reflectValue.Kind() == reflect.Array {
    41  			reflectValue = mustArrayToByteSlice(reflectValue)
    42  		}
    43  		if reflectValue.Type() != reflect.TypeOf([]byte{}) {
    44  			return []byte{}, errors.New("bytes type is neither slice nor array")
    45  		}
    46  		return packBytesSlice(reflectValue.Bytes(), reflectValue.Len()), nil
    47  	case FixedBytesTy, FunctionTy:
    48  		if reflectValue.Kind() == reflect.Array {
    49  			reflectValue = mustArrayToByteSlice(reflectValue)
    50  		}
    51  		return common.RightPadBytes(reflectValue.Bytes(), 32), nil
    52  	default:
    53  		return []byte{}, fmt.Errorf("could not pack element, unknown type: %v", t.T)
    54  	}
    55  }
    56  
    57  // packNum packs the given number (using the reflect value) and will cast it to appropriate number representation.
    58  func packNum(value reflect.Value) []byte {
    59  	switch kind := value.Kind(); kind {
    60  	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
    61  		return math.U256Bytes(new(big.Int).SetUint64(value.Uint()))
    62  	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
    63  		return math.U256Bytes(big.NewInt(value.Int()))
    64  	case reflect.Ptr:
    65  		return math.U256Bytes(new(big.Int).Set(value.Interface().(*big.Int)))
    66  	default:
    67  		panic("abi: fatal error")
    68  	}
    69  }