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