github.com/neatio-net/neatio@v1.7.3-0.20231114194659-f4d7a2226baa/chain/accounts/abi/reflect.go (about) 1 package abi 2 3 import ( 4 "fmt" 5 "reflect" 6 "strings" 7 ) 8 9 func indirect(v reflect.Value) reflect.Value { 10 if v.Kind() == reflect.Ptr && v.Elem().Type() != derefbigT { 11 return indirect(v.Elem()) 12 } 13 return v 14 } 15 16 func indirectInterfaceOrPtr(v reflect.Value) reflect.Value { 17 if (v.Kind() == reflect.Interface || v.Kind() == reflect.Ptr) && v.Elem().IsValid() { 18 return indirect(v.Elem()) 19 } 20 return v 21 } 22 23 func reflectIntKindAndType(unsigned bool, size int) (reflect.Kind, reflect.Type) { 24 switch size { 25 case 8: 26 if unsigned { 27 return reflect.Uint8, uint8T 28 } 29 return reflect.Int8, int8T 30 case 16: 31 if unsigned { 32 return reflect.Uint16, uint16T 33 } 34 return reflect.Int16, int16T 35 case 32: 36 if unsigned { 37 return reflect.Uint32, uint32T 38 } 39 return reflect.Int32, int32T 40 case 64: 41 if unsigned { 42 return reflect.Uint64, uint64T 43 } 44 return reflect.Int64, int64T 45 } 46 return reflect.Ptr, bigT 47 } 48 49 func mustArrayToByteSlice(value reflect.Value) reflect.Value { 50 slice := reflect.MakeSlice(reflect.TypeOf([]byte{}), value.Len(), value.Len()) 51 reflect.Copy(slice, value) 52 return slice 53 } 54 55 func set(dst, src reflect.Value) error { 56 dstType, srcType := dst.Type(), src.Type() 57 switch { 58 case dstType.Kind() == reflect.Interface && dst.Elem().IsValid(): 59 return set(dst.Elem(), src) 60 case dstType.Kind() == reflect.Ptr && dstType.Elem() != derefbigT: 61 return set(dst.Elem(), src) 62 case srcType.AssignableTo(dstType) && dst.CanSet(): 63 dst.Set(src) 64 case dstType.Kind() == reflect.Slice && srcType.Kind() == reflect.Slice: 65 return setSlice(dst, src) 66 default: 67 return fmt.Errorf("abi: cannot unmarshal %v in to %v", src.Type(), dst.Type()) 68 } 69 return nil 70 } 71 72 func setSlice(dst, src reflect.Value) error { 73 slice := reflect.MakeSlice(dst.Type(), src.Len(), src.Len()) 74 for i := 0; i < src.Len(); i++ { 75 v := src.Index(i) 76 reflect.Copy(slice.Index(i), v) 77 } 78 79 dst.Set(slice) 80 return nil 81 } 82 83 func requireAssignable(dst, src reflect.Value) error { 84 if dst.Kind() != reflect.Ptr && dst.Kind() != reflect.Interface { 85 return fmt.Errorf("abi: cannot unmarshal %v into %v", src.Type(), dst.Type()) 86 } 87 return nil 88 } 89 90 func requireUnpackKind(v reflect.Value, t reflect.Type, k reflect.Kind, 91 args Arguments) error { 92 93 switch k { 94 case reflect.Struct: 95 case reflect.Slice, reflect.Array: 96 if minLen := args.LengthNonIndexed(); v.Len() < minLen { 97 return fmt.Errorf("abi: insufficient number of elements in the list/array for unpack, want %d, got %d", 98 minLen, v.Len()) 99 } 100 default: 101 return fmt.Errorf("abi: cannot unmarshal tuple into %v", t) 102 } 103 return nil 104 } 105 106 func mapArgNamesToStructFields(argNames []string, value reflect.Value) (map[string]string, error) { 107 typ := value.Type() 108 109 abi2struct := make(map[string]string) 110 struct2abi := make(map[string]string) 111 112 for i := 0; i < typ.NumField(); i++ { 113 structFieldName := typ.Field(i).Name 114 115 if structFieldName[:1] != strings.ToUpper(structFieldName[:1]) { 116 continue 117 } 118 119 var ok bool 120 var tagName string 121 if tagName, ok = typ.Field(i).Tag.Lookup("abi"); !ok { 122 continue 123 } 124 125 if tagName == "" { 126 return nil, fmt.Errorf("struct: abi tag in '%s' is empty", structFieldName) 127 } 128 129 found := false 130 for _, arg := range argNames { 131 if arg == tagName { 132 if abi2struct[arg] != "" { 133 return nil, fmt.Errorf("struct: abi tag in '%s' already mapped", structFieldName) 134 } 135 136 abi2struct[arg] = structFieldName 137 struct2abi[structFieldName] = arg 138 found = true 139 } 140 } 141 142 if !found { 143 return nil, fmt.Errorf("struct: abi tag '%s' defined but not found in abi", tagName) 144 } 145 } 146 147 for _, argName := range argNames { 148 149 structFieldName := ToCamelCase(argName) 150 151 if structFieldName == "" { 152 return nil, fmt.Errorf("abi: purely underscored output cannot unpack to struct") 153 } 154 155 if abi2struct[argName] != "" { 156 if abi2struct[argName] != structFieldName && 157 struct2abi[structFieldName] == "" && 158 value.FieldByName(structFieldName).IsValid() { 159 return nil, fmt.Errorf("abi: multiple variables maps to the same abi field '%s'", argName) 160 } 161 continue 162 } 163 164 if struct2abi[structFieldName] != "" { 165 return nil, fmt.Errorf("abi: multiple outputs mapping to the same struct field '%s'", structFieldName) 166 } 167 168 if value.FieldByName(structFieldName).IsValid() { 169 170 abi2struct[argName] = structFieldName 171 struct2abi[structFieldName] = argName 172 } else { 173 174 struct2abi[structFieldName] = argName 175 } 176 } 177 return abi2struct, nil 178 }