reflect2.go raw

   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  }
 301