github.com/arieschain/arieschain@v0.0.0-20191023063405-37c074544356/accounts/abi/type.go (about) 1 package abi 2 3 import ( 4 "fmt" 5 "reflect" 6 "regexp" 7 "strconv" 8 "strings" 9 ) 10 11 // Type enumerator 12 const ( 13 IntTy byte = iota 14 UintTy 15 BoolTy 16 StringTy 17 SliceTy 18 ArrayTy 19 AddressTy 20 FixedBytesTy 21 BytesTy 22 HashTy 23 FixedPointTy 24 FunctionTy 25 ) 26 27 // Type is the reflection of the supported argument type 28 type Type struct { 29 Elem *Type 30 31 Kind reflect.Kind 32 Type reflect.Type 33 Size int 34 T byte // Our own type checking 35 36 stringKind string // holds the unparsed string for deriving signatures 37 } 38 39 var ( 40 // typeRegex parses the abi sub types 41 typeRegex = regexp.MustCompile("([a-zA-Z]+)(([0-9]+)(x([0-9]+))?)?") 42 ) 43 44 // NewType creates a new reflection type of abi type given in t. 45 func NewType(t string) (typ Type, err error) { 46 // check that array brackets are equal if they exist 47 if strings.Count(t, "[") != strings.Count(t, "]") { 48 return Type{}, fmt.Errorf("invalid arg type in abi") 49 } 50 51 typ.stringKind = t 52 53 // if there are brackets, get ready to go into slice/array mode and 54 // recursively create the type 55 if strings.Count(t, "[") != 0 { 56 i := strings.LastIndex(t, "[") 57 // recursively embed the type 58 embeddedType, err := NewType(t[:i]) 59 if err != nil { 60 return Type{}, err 61 } 62 // grab the last cell and create a type from there 63 sliced := t[i:] 64 // grab the slice size with regexp 65 re := regexp.MustCompile("[0-9]+") 66 intz := re.FindAllString(sliced, -1) 67 68 if len(intz) == 0 { 69 // is a slice 70 typ.T = SliceTy 71 typ.Kind = reflect.Slice 72 typ.Elem = &embeddedType 73 typ.Type = reflect.SliceOf(embeddedType.Type) 74 } else if len(intz) == 1 { 75 // is a array 76 typ.T = ArrayTy 77 typ.Kind = reflect.Array 78 typ.Elem = &embeddedType 79 typ.Size, err = strconv.Atoi(intz[0]) 80 if err != nil { 81 return Type{}, fmt.Errorf("abi: error parsing variable size: %v", err) 82 } 83 typ.Type = reflect.ArrayOf(typ.Size, embeddedType.Type) 84 } else { 85 return Type{}, fmt.Errorf("invalid formatting of array type") 86 } 87 return typ, err 88 } 89 // parse the type and size of the abi-type. 90 parsedType := typeRegex.FindAllStringSubmatch(t, -1)[0] 91 // varSize is the size of the variable 92 var varSize int 93 if len(parsedType[3]) > 0 { 94 var err error 95 varSize, err = strconv.Atoi(parsedType[2]) 96 if err != nil { 97 return Type{}, fmt.Errorf("abi: error parsing variable size: %v", err) 98 } 99 } else { 100 if parsedType[0] == "uint" || parsedType[0] == "int" { 101 // this should fail because it means that there's something wrong with 102 // the abi type (the compiler should always format it to the size...always) 103 return Type{}, fmt.Errorf("unsupported arg type: %s", t) 104 } 105 } 106 // varType is the parsed abi type 107 switch varType := parsedType[1]; varType { 108 case "int": 109 typ.Kind, typ.Type = reflectIntKindAndType(false, varSize) 110 typ.Size = varSize 111 typ.T = IntTy 112 case "uint": 113 typ.Kind, typ.Type = reflectIntKindAndType(true, varSize) 114 typ.Size = varSize 115 typ.T = UintTy 116 case "bool": 117 typ.Kind = reflect.Bool 118 typ.T = BoolTy 119 typ.Type = reflect.TypeOf(bool(false)) 120 case "address": 121 typ.Kind = reflect.Array 122 typ.Type = addressT 123 typ.Size = 20 124 typ.T = AddressTy 125 case "string": 126 typ.Kind = reflect.String 127 typ.Type = reflect.TypeOf("") 128 typ.T = StringTy 129 case "bytes": 130 if varSize == 0 { 131 typ.T = BytesTy 132 typ.Kind = reflect.Slice 133 typ.Type = reflect.SliceOf(reflect.TypeOf(byte(0))) 134 } else { 135 typ.T = FixedBytesTy 136 typ.Kind = reflect.Array 137 typ.Size = varSize 138 typ.Type = reflect.ArrayOf(varSize, reflect.TypeOf(byte(0))) 139 } 140 case "function": 141 typ.Kind = reflect.Array 142 typ.T = FunctionTy 143 typ.Size = 24 144 typ.Type = reflect.ArrayOf(24, reflect.TypeOf(byte(0))) 145 default: 146 return Type{}, fmt.Errorf("unsupported arg type: %s", t) 147 } 148 149 return 150 } 151 152 // String implements Stringer 153 func (t Type) String() (out string) { 154 return t.stringKind 155 } 156 157 func (t Type) pack(v reflect.Value) ([]byte, error) { 158 // dereference pointer first if it's a pointer 159 v = indirect(v) 160 161 if err := typeCheck(t, v); err != nil { 162 return nil, err 163 } 164 165 if t.T == SliceTy || t.T == ArrayTy { 166 var packed []byte 167 168 for i := 0; i < v.Len(); i++ { 169 val, err := t.Elem.pack(v.Index(i)) 170 if err != nil { 171 return nil, err 172 } 173 packed = append(packed, val...) 174 } 175 if t.T == SliceTy { 176 return packBytesSlice(packed, v.Len()), nil 177 } else if t.T == ArrayTy { 178 return packed, nil 179 } 180 } 181 return packElement(t, v), nil 182 } 183 184 // requireLengthPrefix returns whether the type requires any sort of length 185 // prefixing. 186 func (t Type) requiresLengthPrefix() bool { 187 return t.T == StringTy || t.T == BytesTy || t.T == SliceTy 188 }