github.com/v2pro/plz@v0.0.0-20221028024117-e5f9aec5b631/reflect2/reflect2.go (about) 1 package reflect2 2 3 import ( 4 "reflect" 5 "unsafe" 6 "github.com/v2pro/plz/concurrent" 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 cacheKey := uintptr(unpackEFace(type1).data) 154 typeObj, found := cfg.cache.Load(cacheKey) 155 if found { 156 return typeObj.(Type) 157 } 158 type2 := cfg.wrapType(type1) 159 cfg.cache.Store(cacheKey, type2) 160 return type2 161 } 162 163 func (cfg *frozenConfig) wrapType(type1 reflect.Type) Type { 164 safeType := safeType{Type: type1, cfg: cfg} 165 switch type1.Kind() { 166 case reflect.Struct: 167 if cfg.useSafeImplementation { 168 return &safeStructType{safeType} 169 } 170 return newUnsafeStructType(cfg, type1) 171 case reflect.Array: 172 if cfg.useSafeImplementation { 173 return &safeSliceType{safeType} 174 } 175 return newUnsafeArrayType(cfg, type1) 176 case reflect.Slice: 177 if cfg.useSafeImplementation { 178 return &safeSliceType{safeType} 179 } 180 return newUnsafeSliceType(cfg, type1) 181 case reflect.Map: 182 if cfg.useSafeImplementation { 183 return &safeMapType{safeType} 184 } 185 return newUnsafeMapType(cfg, type1) 186 case reflect.Ptr, reflect.Chan, reflect.Func: 187 if cfg.useSafeImplementation { 188 return &safeMapType{safeType} 189 } 190 return newUnsafePtrType(cfg, type1) 191 case reflect.Interface: 192 if cfg.useSafeImplementation { 193 return &safeMapType{safeType} 194 } 195 if type1.NumMethod() == 0 { 196 return newUnsafeEFaceType(cfg, type1) 197 } 198 return newUnsafeIFaceType(cfg, type1) 199 default: 200 if cfg.useSafeImplementation { 201 return &safeType 202 } 203 return newUnsafeType(cfg, type1) 204 } 205 } 206 207 func TypeOf(obj interface{}) Type { 208 return ConfigUnsafe.TypeOf(obj) 209 } 210 211 func TypeOfPtr(obj interface{}) PtrType { 212 return TypeOf(obj).(PtrType) 213 } 214 215 func Type2(type1 reflect.Type) Type { 216 return ConfigUnsafe.Type2(type1) 217 } 218 219 func PtrTo(typ Type) Type { 220 return Type2(reflect.PtrTo(typ.Type1())) 221 } 222 223 func PtrOf(obj interface{}) unsafe.Pointer { 224 return unpackEFace(obj).data 225 } 226 227 func RTypeOf(obj interface{}) uintptr { 228 return uintptr(unpackEFace(obj).rtype) 229 } 230 231 func IsNil(obj interface{}) bool { 232 if obj == nil { 233 return true 234 } 235 return unpackEFace(obj).data == nil 236 } 237 238 func IsNullable(kind reflect.Kind) bool { 239 switch kind { 240 case reflect.Ptr, reflect.Map, reflect.Chan, reflect.Func, reflect.Slice, reflect.Interface: 241 return true 242 } 243 return false 244 } 245 246 func likePtrKind(kind reflect.Kind) bool { 247 switch kind { 248 case reflect.Ptr, reflect.Map, reflect.Chan, reflect.Func: 249 return true 250 } 251 return false 252 } 253 254 func likePtrType(typ reflect.Type) bool { 255 if likePtrKind(typ.Kind()) { 256 return true 257 } 258 if typ.Kind() == reflect.Struct { 259 if typ.NumField() != 1 { 260 return false 261 } 262 return likePtrType(typ.Field(0).Type) 263 } 264 if typ.Kind() == reflect.Array { 265 if typ.Len() != 1 { 266 return false 267 } 268 return likePtrType(typ.Elem()) 269 } 270 return false 271 } 272 273 // NoEscape hides a pointer from escape analysis. noescape is 274 // the identity function but escape analysis doesn't think the 275 // output depends on the input. noescape is inlined and currently 276 // compiles down to zero instructions. 277 // USE CAREFULLY! 278 //go:nosplit 279 func NoEscape(p unsafe.Pointer) unsafe.Pointer { 280 x := uintptr(p) 281 return unsafe.Pointer(x ^ 0) 282 }