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  }