github.com/linapex/ethereum-dpos-chinese@v0.0.0-20190316121959-b78b3a4a1ece/accounts/abi/type.go (about)

     1  
     2  //<developer>
     3  //    <name>linapex 曹一峰</name>
     4  //    <email>linapex@163.com</email>
     5  //    <wx>superexc</wx>
     6  //    <qqgroup>128148617</qqgroup>
     7  //    <url>https://jsq.ink</url>
     8  //    <role>pku engineer</role>
     9  //    <date>2019-03-16 12:09:26</date>
    10  //</624342583987933184>
    11  
    12  
    13  package abi
    14  
    15  import (
    16  	"fmt"
    17  	"reflect"
    18  	"regexp"
    19  	"strconv"
    20  	"strings"
    21  )
    22  
    23  //类型枚举器
    24  const (
    25  	IntTy byte = iota
    26  	UintTy
    27  	BoolTy
    28  	StringTy
    29  	SliceTy
    30  	ArrayTy
    31  	AddressTy
    32  	FixedBytesTy
    33  	BytesTy
    34  	HashTy
    35  	FixedPointTy
    36  	FunctionTy
    37  )
    38  
    39  //类型是受支持的参数类型的反射
    40  type Type struct {
    41  	Elem *Type
    42  
    43  	Kind reflect.Kind
    44  	Type reflect.Type
    45  	Size int
    46  T    byte //我们自己的类型检查
    47  
    48  stringKind string //保留用于派生签名的未分析字符串
    49  }
    50  
    51  var (
    52  //typeregex解析ABI子类型
    53  	typeRegex = regexp.MustCompile("([a-zA-Z]+)(([0-9]+)(x([0-9]+))?)?")
    54  )
    55  
    56  //new type创建在t中给定的abi类型的新反射类型。
    57  func NewType(t string) (typ Type, err error) {
    58  //检查数组括号是否相等(如果存在)
    59  	if strings.Count(t, "[") != strings.Count(t, "]") {
    60  		return Type{}, fmt.Errorf("invalid arg type in abi")
    61  	}
    62  
    63  	typ.stringKind = t
    64  
    65  //如果有括号,准备进入切片/阵列模式
    66  //递归创建类型
    67  	if strings.Count(t, "[") != 0 {
    68  		i := strings.LastIndex(t, "[")
    69  //递归嵌入类型
    70  		embeddedType, err := NewType(t[:i])
    71  		if err != nil {
    72  			return Type{}, err
    73  		}
    74  //抓取最后一个单元格并从中创建类型
    75  		sliced := t[i:]
    76  //用regexp获取切片大小
    77  		re := regexp.MustCompile("[0-9]+")
    78  		intz := re.FindAllString(sliced, -1)
    79  
    80  		if len(intz) == 0 {
    81  //是一片
    82  			typ.T = SliceTy
    83  			typ.Kind = reflect.Slice
    84  			typ.Elem = &embeddedType
    85  			typ.Type = reflect.SliceOf(embeddedType.Type)
    86  		} else if len(intz) == 1 {
    87  //是一个数组
    88  			typ.T = ArrayTy
    89  			typ.Kind = reflect.Array
    90  			typ.Elem = &embeddedType
    91  			typ.Size, err = strconv.Atoi(intz[0])
    92  			if err != nil {
    93  				return Type{}, fmt.Errorf("abi: error parsing variable size: %v", err)
    94  			}
    95  			typ.Type = reflect.ArrayOf(typ.Size, embeddedType.Type)
    96  		} else {
    97  			return Type{}, fmt.Errorf("invalid formatting of array type")
    98  		}
    99  		return typ, err
   100  	}
   101  //分析ABI类型的类型和大小。
   102  	parsedType := typeRegex.FindAllStringSubmatch(t, -1)[0]
   103  //varsize是变量的大小
   104  	var varSize int
   105  	if len(parsedType[3]) > 0 {
   106  		var err error
   107  		varSize, err = strconv.Atoi(parsedType[2])
   108  		if err != nil {
   109  			return Type{}, fmt.Errorf("abi: error parsing variable size: %v", err)
   110  		}
   111  	} else {
   112  		if parsedType[0] == "uint" || parsedType[0] == "int" {
   113  //这应该失败,因为这意味着
   114  //ABI类型(编译器应始终将其格式化为大小…始终)
   115  			return Type{}, fmt.Errorf("unsupported arg type: %s", t)
   116  		}
   117  	}
   118  //vartype是解析的abi类型
   119  	switch varType := parsedType[1]; varType {
   120  	case "int":
   121  		typ.Kind, typ.Type = reflectIntKindAndType(false, varSize)
   122  		typ.Size = varSize
   123  		typ.T = IntTy
   124  	case "uint":
   125  		typ.Kind, typ.Type = reflectIntKindAndType(true, varSize)
   126  		typ.Size = varSize
   127  		typ.T = UintTy
   128  	case "bool":
   129  		typ.Kind = reflect.Bool
   130  		typ.T = BoolTy
   131  		typ.Type = reflect.TypeOf(bool(false))
   132  	case "address":
   133  		typ.Kind = reflect.Array
   134  		typ.Type = addressT
   135  		typ.Size = 20
   136  		typ.T = AddressTy
   137  	case "string":
   138  		typ.Kind = reflect.String
   139  		typ.Type = reflect.TypeOf("")
   140  		typ.T = StringTy
   141  	case "bytes":
   142  		if varSize == 0 {
   143  			typ.T = BytesTy
   144  			typ.Kind = reflect.Slice
   145  			typ.Type = reflect.SliceOf(reflect.TypeOf(byte(0)))
   146  		} else {
   147  			typ.T = FixedBytesTy
   148  			typ.Kind = reflect.Array
   149  			typ.Size = varSize
   150  			typ.Type = reflect.ArrayOf(varSize, reflect.TypeOf(byte(0)))
   151  		}
   152  	case "function":
   153  		typ.Kind = reflect.Array
   154  		typ.T = FunctionTy
   155  		typ.Size = 24
   156  		typ.Type = reflect.ArrayOf(24, reflect.TypeOf(byte(0)))
   157  	default:
   158  		return Type{}, fmt.Errorf("unsupported arg type: %s", t)
   159  	}
   160  
   161  	return
   162  }
   163  
   164  //字符串实现字符串
   165  func (t Type) String() (out string) {
   166  	return t.stringKind
   167  }
   168  
   169  func (t Type) pack(v reflect.Value) ([]byte, error) {
   170  //如果指针是指针,则先取消引用指针
   171  	v = indirect(v)
   172  
   173  	if err := typeCheck(t, v); err != nil {
   174  		return nil, err
   175  	}
   176  
   177  	if t.T == SliceTy || t.T == ArrayTy {
   178  		var packed []byte
   179  
   180  		for i := 0; i < v.Len(); i++ {
   181  			val, err := t.Elem.pack(v.Index(i))
   182  			if err != nil {
   183  				return nil, err
   184  			}
   185  			packed = append(packed, val...)
   186  		}
   187  		if t.T == SliceTy {
   188  			return packBytesSlice(packed, v.Len()), nil
   189  		} else if t.T == ArrayTy {
   190  			return packed, nil
   191  		}
   192  	}
   193  	return packElement(t, v), nil
   194  }
   195  
   196  //RequireLengthPrefix返回类型是否需要任何长度
   197  //前缀。
   198  func (t Type) requiresLengthPrefix() bool {
   199  	return t.T == StringTy || t.T == BytesTy || t.T == SliceTy
   200  }
   201