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 }