github.com/modern-go/Reflect2@v1.0.1/reflect2.go (about)

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