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