github.com/modern-go/Reflect2@v1.0.1/reflect2.go (about) 1 package reflect2 2 3 import ( 4 "github.com/modern-go/concurrent" 5 "reflect" 6 "unsafe" 7 ) 8 9 type Type interface { 10 Kind() reflect.Kind 11 // New return pointer to data of this type 12 New() interface{} 13 // UnsafeNew return the allocated space pointed by unsafe.Pointer 14 UnsafeNew() unsafe.Pointer 15 // PackEFace cast a unsafe pointer to object represented pointer 16 PackEFace(ptr unsafe.Pointer) interface{} 17 // Indirect dereference object represented pointer to this type 18 Indirect(obj interface{}) interface{} 19 // UnsafeIndirect dereference pointer to this type 20 UnsafeIndirect(ptr unsafe.Pointer) interface{} 21 // Type1 returns reflect.Type 22 Type1() reflect.Type 23 Implements(thatType Type) bool 24 String() string 25 RType() uintptr 26 // interface{} of this type has pointer like behavior 27 LikePtr() bool 28 IsNullable() bool 29 IsNil(obj interface{}) bool 30 UnsafeIsNil(ptr unsafe.Pointer) bool 31 Set(obj interface{}, val interface{}) 32 UnsafeSet(ptr unsafe.Pointer, val unsafe.Pointer) 33 AssignableTo(anotherType Type) bool 34 } 35 36 type ListType interface { 37 Type 38 Elem() Type 39 SetIndex(obj interface{}, index int, elem interface{}) 40 UnsafeSetIndex(obj unsafe.Pointer, index int, elem unsafe.Pointer) 41 GetIndex(obj interface{}, index int) interface{} 42 UnsafeGetIndex(obj unsafe.Pointer, index int) unsafe.Pointer 43 } 44 45 type ArrayType interface { 46 ListType 47 Len() int 48 } 49 50 type SliceType interface { 51 ListType 52 MakeSlice(length int, cap int) interface{} 53 UnsafeMakeSlice(length int, cap int) unsafe.Pointer 54 Grow(obj interface{}, newLength int) 55 UnsafeGrow(ptr unsafe.Pointer, newLength int) 56 Append(obj interface{}, elem interface{}) 57 UnsafeAppend(obj unsafe.Pointer, elem unsafe.Pointer) 58 LengthOf(obj interface{}) int 59 UnsafeLengthOf(ptr unsafe.Pointer) int 60 SetNil(obj interface{}) 61 UnsafeSetNil(ptr unsafe.Pointer) 62 Cap(obj interface{}) int 63 UnsafeCap(ptr unsafe.Pointer) int 64 } 65 66 type StructType interface { 67 Type 68 NumField() int 69 Field(i int) StructField 70 FieldByName(name string) StructField 71 FieldByIndex(index []int) StructField 72 FieldByNameFunc(match func(string) bool) StructField 73 } 74 75 type StructField interface { 76 Offset() uintptr 77 Name() string 78 PkgPath() string 79 Type() Type 80 Tag() reflect.StructTag 81 Index() []int 82 Anonymous() bool 83 Set(obj interface{}, value interface{}) 84 UnsafeSet(obj unsafe.Pointer, value unsafe.Pointer) 85 Get(obj interface{}) interface{} 86 UnsafeGet(obj unsafe.Pointer) unsafe.Pointer 87 } 88 89 type MapType interface { 90 Type 91 Key() Type 92 Elem() Type 93 MakeMap(cap int) interface{} 94 UnsafeMakeMap(cap int) unsafe.Pointer 95 SetIndex(obj interface{}, key interface{}, elem interface{}) 96 UnsafeSetIndex(obj unsafe.Pointer, key unsafe.Pointer, elem unsafe.Pointer) 97 TryGetIndex(obj interface{}, key interface{}) (interface{}, bool) 98 GetIndex(obj interface{}, key interface{}) interface{} 99 UnsafeGetIndex(obj unsafe.Pointer, key unsafe.Pointer) unsafe.Pointer 100 Iterate(obj interface{}) MapIterator 101 UnsafeIterate(obj unsafe.Pointer) MapIterator 102 } 103 104 type MapIterator interface { 105 HasNext() bool 106 Next() (key interface{}, elem interface{}) 107 UnsafeNext() (key unsafe.Pointer, elem unsafe.Pointer) 108 } 109 110 type PtrType interface { 111 Type 112 Elem() Type 113 } 114 115 type InterfaceType interface { 116 NumMethod() int 117 } 118 119 type Config struct { 120 UseSafeImplementation bool 121 } 122 123 type API interface { 124 TypeOf(obj interface{}) Type 125 Type2(type1 reflect.Type) Type 126 } 127 128 var ConfigUnsafe = Config{UseSafeImplementation: false}.Froze() 129 var ConfigSafe = Config{UseSafeImplementation: true}.Froze() 130 131 type frozenConfig struct { 132 useSafeImplementation bool 133 cache *concurrent.Map 134 } 135 136 func (cfg Config) Froze() *frozenConfig { 137 return &frozenConfig{ 138 useSafeImplementation: cfg.UseSafeImplementation, 139 cache: concurrent.NewMap(), 140 } 141 } 142 143 func (cfg *frozenConfig) TypeOf(obj interface{}) Type { 144 cacheKey := uintptr(unpackEFace(obj).rtype) 145 typeObj, found := cfg.cache.Load(cacheKey) 146 if found { 147 return typeObj.(Type) 148 } 149 return cfg.Type2(reflect.TypeOf(obj)) 150 } 151 152 func (cfg *frozenConfig) Type2(type1 reflect.Type) Type { 153 if type1 == nil { 154 return nil 155 } 156 cacheKey := uintptr(unpackEFace(type1).data) 157 typeObj, found := cfg.cache.Load(cacheKey) 158 if found { 159 return typeObj.(Type) 160 } 161 type2 := cfg.wrapType(type1) 162 cfg.cache.Store(cacheKey, type2) 163 return type2 164 } 165 166 func (cfg *frozenConfig) wrapType(type1 reflect.Type) Type { 167 safeType := safeType{Type: type1, cfg: cfg} 168 switch type1.Kind() { 169 case reflect.Struct: 170 if cfg.useSafeImplementation { 171 return &safeStructType{safeType} 172 } 173 return newUnsafeStructType(cfg, type1) 174 case reflect.Array: 175 if cfg.useSafeImplementation { 176 return &safeSliceType{safeType} 177 } 178 return newUnsafeArrayType(cfg, type1) 179 case reflect.Slice: 180 if cfg.useSafeImplementation { 181 return &safeSliceType{safeType} 182 } 183 return newUnsafeSliceType(cfg, type1) 184 case reflect.Map: 185 if cfg.useSafeImplementation { 186 return &safeMapType{safeType} 187 } 188 return newUnsafeMapType(cfg, type1) 189 case reflect.Ptr, reflect.Chan, reflect.Func: 190 if cfg.useSafeImplementation { 191 return &safeMapType{safeType} 192 } 193 return newUnsafePtrType(cfg, type1) 194 case reflect.Interface: 195 if cfg.useSafeImplementation { 196 return &safeMapType{safeType} 197 } 198 if type1.NumMethod() == 0 { 199 return newUnsafeEFaceType(cfg, type1) 200 } 201 return newUnsafeIFaceType(cfg, type1) 202 default: 203 if cfg.useSafeImplementation { 204 return &safeType 205 } 206 return newUnsafeType(cfg, type1) 207 } 208 } 209 210 func TypeOf(obj interface{}) Type { 211 return ConfigUnsafe.TypeOf(obj) 212 } 213 214 func TypeOfPtr(obj interface{}) PtrType { 215 return TypeOf(obj).(PtrType) 216 } 217 218 func Type2(type1 reflect.Type) Type { 219 if type1 == nil { 220 return nil 221 } 222 return ConfigUnsafe.Type2(type1) 223 } 224 225 func PtrTo(typ Type) Type { 226 return Type2(reflect.PtrTo(typ.Type1())) 227 } 228 229 func PtrOf(obj interface{}) unsafe.Pointer { 230 return unpackEFace(obj).data 231 } 232 233 func RTypeOf(obj interface{}) uintptr { 234 return uintptr(unpackEFace(obj).rtype) 235 } 236 237 func IsNil(obj interface{}) bool { 238 if obj == nil { 239 return true 240 } 241 return unpackEFace(obj).data == nil 242 } 243 244 func IsNullable(kind reflect.Kind) bool { 245 switch kind { 246 case reflect.Ptr, reflect.Map, reflect.Chan, reflect.Func, reflect.Slice, reflect.Interface: 247 return true 248 } 249 return false 250 } 251 252 func likePtrKind(kind reflect.Kind) bool { 253 switch kind { 254 case reflect.Ptr, reflect.Map, reflect.Chan, reflect.Func: 255 return true 256 } 257 return false 258 } 259 260 func likePtrType(typ reflect.Type) bool { 261 if likePtrKind(typ.Kind()) { 262 return true 263 } 264 if typ.Kind() == reflect.Struct { 265 if typ.NumField() != 1 { 266 return false 267 } 268 return likePtrType(typ.Field(0).Type) 269 } 270 if typ.Kind() == reflect.Array { 271 if typ.Len() != 1 { 272 return false 273 } 274 return likePtrType(typ.Elem()) 275 } 276 return false 277 } 278 279 // NoEscape hides a pointer from escape analysis. noescape is 280 // the identity function but escape analysis doesn't think the 281 // output depends on the input. noescape is inlined and currently 282 // compiles down to zero instructions. 283 // USE CAREFULLY! 284 //go:nosplit 285 func NoEscape(p unsafe.Pointer) unsafe.Pointer { 286 x := uintptr(p) 287 return unsafe.Pointer(x ^ 0) 288 } 289 290 func UnsafeCastString(str string) []byte { 291 stringHeader := (*reflect.StringHeader)(unsafe.Pointer(&str)) 292 sliceHeader := &reflect.SliceHeader{ 293 Data: stringHeader.Data, 294 Cap: stringHeader.Len, 295 Len: stringHeader.Len, 296 } 297 return *(*[]byte)(unsafe.Pointer(sliceHeader)) 298 }