github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/accounts/abi/type.go (about)

     1  
     2  //此源码被清华学神尹成大魔王专业翻译分析并修改
     3  //尹成QQ77025077
     4  //尹成微信18510341407
     5  //尹成所在QQ群721929980
     6  //尹成邮箱 yinc13@mails.tsinghua.edu.cn
     7  //尹成毕业于清华大学,微软区块链领域全球最有价值专家
     8  //https://mvp.microsoft.com/zh-cn/PublicProfile/4033620
     9  //版权所有2015 Go Ethereum作者
    10  //此文件是Go以太坊库的一部分。
    11  //
    12  //Go-Ethereum库是免费软件:您可以重新分发它和/或修改
    13  //根据GNU发布的较低通用公共许可证的条款
    14  //自由软件基金会,或者许可证的第3版,或者
    15  //(由您选择)任何更高版本。
    16  //
    17  //Go以太坊图书馆的发行目的是希望它会有用,
    18  //但没有任何保证;甚至没有
    19  //适销性或特定用途的适用性。见
    20  //GNU较低的通用公共许可证,了解更多详细信息。
    21  //
    22  //你应该收到一份GNU较低级别的公共许可证副本
    23  //以及Go以太坊图书馆。如果没有,请参见<http://www.gnu.org/licenses/>。
    24  
    25  package abi
    26  
    27  import (
    28  	"fmt"
    29  	"reflect"
    30  	"regexp"
    31  	"strconv"
    32  	"strings"
    33  )
    34  
    35  //类型枚举器
    36  const (
    37  	IntTy byte = iota
    38  	UintTy
    39  	BoolTy
    40  	StringTy
    41  	SliceTy
    42  	ArrayTy
    43  	AddressTy
    44  	FixedBytesTy
    45  	BytesTy
    46  	HashTy
    47  	FixedPointTy
    48  	FunctionTy
    49  )
    50  
    51  //类型是受支持的参数类型的反射
    52  type Type struct {
    53  	Elem *Type
    54  
    55  	Kind reflect.Kind
    56  	Type reflect.Type
    57  	Size int
    58  T    byte //我们自己的类型检查
    59  
    60  stringKind string //保留用于派生签名的未分析字符串
    61  }
    62  
    63  var (
    64  //typeregex解析ABI子类型
    65  	typeRegex = regexp.MustCompile("([a-zA-Z]+)(([0-9]+)(x([0-9]+))?)?")
    66  )
    67  
    68  //new type创建在t中给定的abi类型的新反射类型。
    69  func NewType(t string) (typ Type, err error) {
    70  //检查数组括号是否相等(如果存在)
    71  	if strings.Count(t, "[") != strings.Count(t, "]") {
    72  		return Type{}, fmt.Errorf("invalid arg type in abi")
    73  	}
    74  
    75  	typ.stringKind = t
    76  
    77  //如果有括号,准备进入切片/阵列模式
    78  //递归创建类型
    79  	if strings.Count(t, "[") != 0 {
    80  		i := strings.LastIndex(t, "[")
    81  //递归嵌入类型
    82  		embeddedType, err := NewType(t[:i])
    83  		if err != nil {
    84  			return Type{}, err
    85  		}
    86  //抓取最后一个单元格并从中创建类型
    87  		sliced := t[i:]
    88  //用regexp获取切片大小
    89  		re := regexp.MustCompile("[0-9]+")
    90  		intz := re.FindAllString(sliced, -1)
    91  
    92  		if len(intz) == 0 {
    93  //是一片
    94  			typ.T = SliceTy
    95  			typ.Kind = reflect.Slice
    96  			typ.Elem = &embeddedType
    97  			typ.Type = reflect.SliceOf(embeddedType.Type)
    98  		} else if len(intz) == 1 {
    99  //是一个数组
   100  			typ.T = ArrayTy
   101  			typ.Kind = reflect.Array
   102  			typ.Elem = &embeddedType
   103  			typ.Size, err = strconv.Atoi(intz[0])
   104  			if err != nil {
   105  				return Type{}, fmt.Errorf("abi: error parsing variable size: %v", err)
   106  			}
   107  			typ.Type = reflect.ArrayOf(typ.Size, embeddedType.Type)
   108  		} else {
   109  			return Type{}, fmt.Errorf("invalid formatting of array type")
   110  		}
   111  		return typ, err
   112  	}
   113  //分析ABI类型的类型和大小。
   114  	parsedType := typeRegex.FindAllStringSubmatch(t, -1)[0]
   115  //varsize是变量的大小
   116  	var varSize int
   117  	if len(parsedType[3]) > 0 {
   118  		var err error
   119  		varSize, err = strconv.Atoi(parsedType[2])
   120  		if err != nil {
   121  			return Type{}, fmt.Errorf("abi: error parsing variable size: %v", err)
   122  		}
   123  	} else {
   124  		if parsedType[0] == "uint" || parsedType[0] == "int" {
   125  //这应该失败,因为这意味着
   126  //ABI类型(编译器应始终将其格式化为大小…始终)
   127  			return Type{}, fmt.Errorf("unsupported arg type: %s", t)
   128  		}
   129  	}
   130  //vartype是解析的abi类型
   131  	switch varType := parsedType[1]; varType {
   132  	case "int":
   133  		typ.Kind, typ.Type = reflectIntKindAndType(false, varSize)
   134  		typ.Size = varSize
   135  		typ.T = IntTy
   136  	case "uint":
   137  		typ.Kind, typ.Type = reflectIntKindAndType(true, varSize)
   138  		typ.Size = varSize
   139  		typ.T = UintTy
   140  	case "bool":
   141  		typ.Kind = reflect.Bool
   142  		typ.T = BoolTy
   143  		typ.Type = reflect.TypeOf(bool(false))
   144  	case "address":
   145  		typ.Kind = reflect.Array
   146  		typ.Type = addressT
   147  		typ.Size = 20
   148  		typ.T = AddressTy
   149  	case "string":
   150  		typ.Kind = reflect.String
   151  		typ.Type = reflect.TypeOf("")
   152  		typ.T = StringTy
   153  	case "bytes":
   154  		if varSize == 0 {
   155  			typ.T = BytesTy
   156  			typ.Kind = reflect.Slice
   157  			typ.Type = reflect.SliceOf(reflect.TypeOf(byte(0)))
   158  		} else {
   159  			typ.T = FixedBytesTy
   160  			typ.Kind = reflect.Array
   161  			typ.Size = varSize
   162  			typ.Type = reflect.ArrayOf(varSize, reflect.TypeOf(byte(0)))
   163  		}
   164  	case "function":
   165  		typ.Kind = reflect.Array
   166  		typ.T = FunctionTy
   167  		typ.Size = 24
   168  		typ.Type = reflect.ArrayOf(24, reflect.TypeOf(byte(0)))
   169  	default:
   170  		return Type{}, fmt.Errorf("unsupported arg type: %s", t)
   171  	}
   172  
   173  	return
   174  }
   175  
   176  //字符串实现字符串
   177  func (t Type) String() (out string) {
   178  	return t.stringKind
   179  }
   180  
   181  func (t Type) pack(v reflect.Value) ([]byte, error) {
   182  //如果指针是指针,则先取消引用指针
   183  	v = indirect(v)
   184  
   185  	if err := typeCheck(t, v); err != nil {
   186  		return nil, err
   187  	}
   188  
   189  	if t.T == SliceTy || t.T == ArrayTy {
   190  		var packed []byte
   191  
   192  		for i := 0; i < v.Len(); i++ {
   193  			val, err := t.Elem.pack(v.Index(i))
   194  			if err != nil {
   195  				return nil, err
   196  			}
   197  			packed = append(packed, val...)
   198  		}
   199  		if t.T == SliceTy {
   200  			return packBytesSlice(packed, v.Len()), nil
   201  		} else if t.T == ArrayTy {
   202  			return packed, nil
   203  		}
   204  	}
   205  	return packElement(t, v), nil
   206  }
   207  
   208  //RequireLengthPrefix返回类型是否需要任何长度
   209  //前缀。
   210  func (t Type) requiresLengthPrefix() bool {
   211  	return t.T == StringTy || t.T == BytesTy || t.T == SliceTy
   212  }