github.com/digdeepmining/go-atheios@v1.5.13-0.20180902133602-d5687a2e6f43/accounts/abi/type.go (about)

     1  // Copyright 2015 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  	"regexp"
    23  	"strconv"
    24  )
    25  
    26  const (
    27  	IntTy byte = iota
    28  	UintTy
    29  	BoolTy
    30  	StringTy
    31  	SliceTy
    32  	AddressTy
    33  	FixedBytesTy
    34  	BytesTy
    35  	HashTy
    36  	FixedpointTy
    37  	FunctionTy
    38  )
    39  
    40  // Type is the reflection of the supported argument type
    41  type Type struct {
    42  	IsSlice, IsArray bool
    43  	SliceSize        int
    44  
    45  	Elem *Type
    46  
    47  	Kind reflect.Kind
    48  	Type reflect.Type
    49  	Size int
    50  	T    byte // Our own type checking
    51  
    52  	stringKind string // holds the unparsed string for deriving signatures
    53  }
    54  
    55  var (
    56  	// fullTypeRegex parses the abi types
    57  	//
    58  	// Types can be in the format of:
    59  	//
    60  	// 	Input  = Type [ "[" [ Number ] "]" ] Name .
    61  	// 	Type   = [ "u" ] "int" [ Number ] [ x ] [ Number ].
    62  	//
    63  	// Examples:
    64  	//
    65  	//      string     int       uint       fixed
    66  	//      string32   int8      uint8      uint[]
    67  	//      address    int256    uint256    fixed128x128[2]
    68  	fullTypeRegex = regexp.MustCompile(`([a-zA-Z0-9]+)(\[([0-9]*)\])?`)
    69  	// typeRegex parses the abi sub types
    70  	typeRegex = regexp.MustCompile("([a-zA-Z]+)(([0-9]+)(x([0-9]+))?)?")
    71  )
    72  
    73  // NewType creates a new reflection type of abi type given in t.
    74  func NewType(t string) (typ Type, err error) {
    75  	res := fullTypeRegex.FindAllStringSubmatch(t, -1)[0]
    76  	// check if type is slice and parse type.
    77  	switch {
    78  	case res[3] != "":
    79  		// err is ignored. Already checked for number through the regexp
    80  		typ.SliceSize, _ = strconv.Atoi(res[3])
    81  		typ.IsArray = true
    82  	case res[2] != "":
    83  		typ.IsSlice, typ.SliceSize = true, -1
    84  	case res[0] == "":
    85  		return Type{}, fmt.Errorf("abi: type parse error: %s", t)
    86  	}
    87  	if typ.IsArray || typ.IsSlice {
    88  		sliceType, err := NewType(res[1])
    89  		if err != nil {
    90  			return Type{}, err
    91  		}
    92  		typ.Elem = &sliceType
    93  		typ.stringKind = sliceType.stringKind + t[len(res[1]):]
    94  		// Although we know that this is an array, we cannot return
    95  		// as we don't know the type of the element, however, if it
    96  		// is still an array, then don't determine the type.
    97  		if typ.Elem.IsArray || typ.Elem.IsSlice {
    98  			return typ, nil
    99  		}
   100  	}
   101  
   102  	// parse the type and size of the abi-type.
   103  	parsedType := typeRegex.FindAllStringSubmatch(res[1], -1)[0]
   104  	// varSize is the size of the variable
   105  	var varSize int
   106  	if len(parsedType[3]) > 0 {
   107  		var err error
   108  		varSize, err = strconv.Atoi(parsedType[2])
   109  		if err != nil {
   110  			return Type{}, fmt.Errorf("abi: error parsing variable size: %v", err)
   111  		}
   112  	}
   113  	// varType is the parsed abi type
   114  	varType := parsedType[1]
   115  	// substitute canonical integer
   116  	if varSize == 0 && (varType == "int" || varType == "uint") {
   117  		varSize = 256
   118  		t += "256"
   119  	}
   120  
   121  	// only set stringKind if not array or slice, as for those,
   122  	// the correct string type has been set
   123  	if !(typ.IsArray || typ.IsSlice) {
   124  		typ.stringKind = t
   125  	}
   126  
   127  	switch varType {
   128  	case "int":
   129  		typ.Kind = reflectIntKind(false, varSize)
   130  		typ.Type = big_t
   131  		typ.Size = varSize
   132  		typ.T = IntTy
   133  	case "uint":
   134  		typ.Kind = reflectIntKind(true, varSize)
   135  		typ.Type = ubig_t
   136  		typ.Size = varSize
   137  		typ.T = UintTy
   138  	case "bool":
   139  		typ.Kind = reflect.Bool
   140  		typ.T = BoolTy
   141  	case "address":
   142  		typ.Kind = reflect.Array
   143  		typ.Type = address_t
   144  		typ.Size = 20
   145  		typ.T = AddressTy
   146  	case "string":
   147  		typ.Kind = reflect.String
   148  		typ.Size = -1
   149  		typ.T = StringTy
   150  	case "bytes":
   151  		sliceType, _ := NewType("uint8")
   152  		typ.Elem = &sliceType
   153  		if varSize == 0 {
   154  			typ.IsSlice = true
   155  			typ.T = BytesTy
   156  			typ.SliceSize = -1
   157  		} else {
   158  			typ.IsArray = true
   159  			typ.T = FixedBytesTy
   160  			typ.SliceSize = varSize
   161  		}
   162  	case "function":
   163  		sliceType, _ := NewType("uint8")
   164  		typ.Elem = &sliceType
   165  		typ.IsArray = true
   166  		typ.T = FunctionTy
   167  		typ.SliceSize = 24
   168  	default:
   169  		return Type{}, fmt.Errorf("unsupported arg type: %s", t)
   170  	}
   171  
   172  	return
   173  }
   174  
   175  // String implements Stringer
   176  func (t Type) String() (out string) {
   177  	return t.stringKind
   178  }
   179  
   180  func (t Type) pack(v reflect.Value) ([]byte, error) {
   181  	// dereference pointer first if it's a pointer
   182  	v = indirect(v)
   183  
   184  	if err := typeCheck(t, v); err != nil {
   185  		return nil, err
   186  	}
   187  
   188  	if (t.IsSlice || t.IsArray) && t.T != BytesTy && t.T != FixedBytesTy && t.T != FunctionTy {
   189  		var packed []byte
   190  
   191  		for i := 0; i < v.Len(); i++ {
   192  			val, err := t.Elem.pack(v.Index(i))
   193  			if err != nil {
   194  				return nil, err
   195  			}
   196  			packed = append(packed, val...)
   197  		}
   198  		if t.IsSlice {
   199  			return packBytesSlice(packed, v.Len()), nil
   200  		} else if t.IsArray {
   201  			return packed, nil
   202  		}
   203  	}
   204  
   205  	return packElement(t, v), nil
   206  }
   207  
   208  // requireLengthPrefix returns whether the type requires any sort of length
   209  // prefixing.
   210  func (t Type) requiresLengthPrefix() bool {
   211  	return t.T != FixedBytesTy && (t.T == StringTy || t.T == BytesTy || t.IsSlice)
   212  }