gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

reflect2.go (7331B)


      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 }