text: package reflect2
  
  import (
  	"github.com/modern-go/concurrent"
  	"reflect"
  	"unsafe"
  )
  
  type Type interface {
  	Kind() reflect.Kind
  	// New return pointer to data of this type
  	New() interface{}
  	// UnsafeNew return the allocated space pointed by unsafe.Pointer
  	UnsafeNew() unsafe.Pointer
  	// PackEFace cast a unsafe pointer to object represented pointer
  	PackEFace(ptr unsafe.Pointer) interface{}
  	// Indirect dereference object represented pointer to this type
  	Indirect(obj interface{}) interface{}
  	// UnsafeIndirect dereference pointer to this type
  	UnsafeIndirect(ptr unsafe.Pointer) interface{}
  	// Type1 returns reflect.Type
  	Type1() reflect.Type
  	Implements(thatType Type) bool
  	String() string
  	RType() uintptr
  	// interface{} of this type has pointer like behavior
  	LikePtr() bool
  	IsNullable() bool
  	IsNil(obj interface{}) bool
  	UnsafeIsNil(ptr unsafe.Pointer) bool
  	Set(obj interface{}, val interface{})
  	UnsafeSet(ptr unsafe.Pointer, val unsafe.Pointer)
  	AssignableTo(anotherType Type) bool
  }
  
  type ListType interface {
  	Type
  	Elem() Type
  	SetIndex(obj interface{}, index int, elem interface{})
  	UnsafeSetIndex(obj unsafe.Pointer, index int, elem unsafe.Pointer)
  	GetIndex(obj interface{}, index int) interface{}
  	UnsafeGetIndex(obj unsafe.Pointer, index int) unsafe.Pointer
  }
  
  type ArrayType interface {
  	ListType
  	Len() int
  }
  
  type SliceType interface {
  	ListType
  	MakeSlice(length int, cap int) interface{}
  	UnsafeMakeSlice(length int, cap int) unsafe.Pointer
  	Grow(obj interface{}, newLength int)
  	UnsafeGrow(ptr unsafe.Pointer, newLength int)
  	Append(obj interface{}, elem interface{})
  	UnsafeAppend(obj unsafe.Pointer, elem unsafe.Pointer)
  	LengthOf(obj interface{}) int
  	UnsafeLengthOf(ptr unsafe.Pointer) int
  	SetNil(obj interface{})
  	UnsafeSetNil(ptr unsafe.Pointer)
  	Cap(obj interface{}) int
  	UnsafeCap(ptr unsafe.Pointer) int
  }
  
  type StructType interface {
  	Type
  	NumField() int
  	Field(i int) StructField
  	FieldByName(name string) StructField
  	FieldByIndex(index []int) StructField
  	FieldByNameFunc(match func(string) bool) StructField
  }
  
  type StructField interface {
  	Offset() uintptr
  	Name() string
  	PkgPath() string
  	Type() Type
  	Tag() reflect.StructTag
  	Index() []int
  	Anonymous() bool
  	Set(obj interface{}, value interface{})
  	UnsafeSet(obj unsafe.Pointer, value unsafe.Pointer)
  	Get(obj interface{}) interface{}
  	UnsafeGet(obj unsafe.Pointer) unsafe.Pointer
  }
  
  type MapType interface {
  	Type
  	Key() Type
  	Elem() Type
  	MakeMap(cap int) interface{}
  	UnsafeMakeMap(cap int) unsafe.Pointer
  	SetIndex(obj interface{}, key interface{}, elem interface{})
  	UnsafeSetIndex(obj unsafe.Pointer, key unsafe.Pointer, elem unsafe.Pointer)
  	TryGetIndex(obj interface{}, key interface{}) (interface{}, bool)
  	GetIndex(obj interface{}, key interface{}) interface{}
  	UnsafeGetIndex(obj unsafe.Pointer, key unsafe.Pointer) unsafe.Pointer
  	Iterate(obj interface{}) MapIterator
  	UnsafeIterate(obj unsafe.Pointer) MapIterator
  }
  
  type MapIterator interface {
  	HasNext() bool
  	Next() (key interface{}, elem interface{})
  	UnsafeNext() (key unsafe.Pointer, elem unsafe.Pointer)
  }
  
  type PtrType interface {
  	Type
  	Elem() Type
  }
  
  type InterfaceType interface {
  	NumMethod() int
  }
  
  type Config struct {
  	UseSafeImplementation bool
  }
  
  type API interface {
  	TypeOf(obj interface{}) Type
  	Type2(type1 reflect.Type) Type
  }
  
  var ConfigUnsafe = Config{UseSafeImplementation: false}.Froze()
  var ConfigSafe = Config{UseSafeImplementation: true}.Froze()
  
  type frozenConfig struct {
  	useSafeImplementation bool
  	cache                 *concurrent.Map
  }
  
  func (cfg Config) Froze() *frozenConfig {
  	return &frozenConfig{
  		useSafeImplementation: cfg.UseSafeImplementation,
  		cache: concurrent.NewMap(),
  	}
  }
  
  func (cfg *frozenConfig) TypeOf(obj interface{}) Type {
  	cacheKey := uintptr(unpackEFace(obj).rtype)
  	typeObj, found := cfg.cache.Load(cacheKey)
  	if found {
  		return typeObj.(Type)
  	}
  	return cfg.Type2(reflect.TypeOf(obj))
  }
  
  func (cfg *frozenConfig) Type2(type1 reflect.Type) Type {
  	if type1 == nil {
  		return nil
  	}
  	cacheKey := uintptr(unpackEFace(type1).data)
  	typeObj, found := cfg.cache.Load(cacheKey)
  	if found {
  		return typeObj.(Type)
  	}
  	type2 := cfg.wrapType(type1)
  	cfg.cache.Store(cacheKey, type2)
  	return type2
  }
  
  func (cfg *frozenConfig) wrapType(type1 reflect.Type) Type {
  	safeType := safeType{Type: type1, cfg: cfg}
  	switch type1.Kind() {
  	case reflect.Struct:
  		if cfg.useSafeImplementation {
  			return &safeStructType{safeType}
  		}
  		return newUnsafeStructType(cfg, type1)
  	case reflect.Array:
  		if cfg.useSafeImplementation {
  			return &safeSliceType{safeType}
  		}
  		return newUnsafeArrayType(cfg, type1)
  	case reflect.Slice:
  		if cfg.useSafeImplementation {
  			return &safeSliceType{safeType}
  		}
  		return newUnsafeSliceType(cfg, type1)
  	case reflect.Map:
  		if cfg.useSafeImplementation {
  			return &safeMapType{safeType}
  		}
  		return newUnsafeMapType(cfg, type1)
  	case reflect.Ptr, reflect.Chan, reflect.Func:
  		if cfg.useSafeImplementation {
  			return &safeMapType{safeType}
  		}
  		return newUnsafePtrType(cfg, type1)
  	case reflect.Interface:
  		if cfg.useSafeImplementation {
  			return &safeMapType{safeType}
  		}
  		if type1.NumMethod() == 0 {
  			return newUnsafeEFaceType(cfg, type1)
  		}
  		return newUnsafeIFaceType(cfg, type1)
  	default:
  		if cfg.useSafeImplementation {
  			return &safeType
  		}
  		return newUnsafeType(cfg, type1)
  	}
  }
  
  func TypeOf(obj interface{}) Type {
  	return ConfigUnsafe.TypeOf(obj)
  }
  
  func TypeOfPtr(obj interface{}) PtrType {
  	return TypeOf(obj).(PtrType)
  }
  
  func Type2(type1 reflect.Type) Type {
  	if type1 == nil {
  		return nil
  	}
  	return ConfigUnsafe.Type2(type1)
  }
  
  func PtrTo(typ Type) Type {
  	return Type2(reflect.PtrTo(typ.Type1()))
  }
  
  func PtrOf(obj interface{}) unsafe.Pointer {
  	return unpackEFace(obj).data
  }
  
  func RTypeOf(obj interface{}) uintptr {
  	return uintptr(unpackEFace(obj).rtype)
  }
  
  func IsNil(obj interface{}) bool {
  	if obj == nil {
  		return true
  	}
  	return unpackEFace(obj).data == nil
  }
  
  func IsNullable(kind reflect.Kind) bool {
  	switch kind {
  	case reflect.Ptr, reflect.Map, reflect.Chan, reflect.Func, reflect.Slice, reflect.Interface:
  		return true
  	}
  	return false
  }
  
  func likePtrKind(kind reflect.Kind) bool {
  	switch kind {
  	case reflect.Ptr, reflect.Map, reflect.Chan, reflect.Func:
  		return true
  	}
  	return false
  }
  
  func likePtrType(typ reflect.Type) bool {
  	if likePtrKind(typ.Kind()) {
  		return true
  	}
  	if typ.Kind() == reflect.Struct {
  		if typ.NumField() != 1 {
  			return false
  		}
  		return likePtrType(typ.Field(0).Type)
  	}
  	if typ.Kind() == reflect.Array {
  		if typ.Len() != 1 {
  			return false
  		}
  		return likePtrType(typ.Elem())
  	}
  	return false
  }
  
  // NoEscape hides a pointer from escape analysis.  noescape is
  // the identity function but escape analysis doesn't think the
  // output depends on the input.  noescape is inlined and currently
  // compiles down to zero instructions.
  // USE CAREFULLY!
  //go:nosplit
  func NoEscape(p unsafe.Pointer) unsafe.Pointer {
  	x := uintptr(p)
  	return unsafe.Pointer(x ^ 0)
  }
  
  func UnsafeCastString(str string) []byte {
  	stringHeader := (*reflect.StringHeader)(unsafe.Pointer(&str))
  	sliceHeader := &reflect.SliceHeader{
  		Data: stringHeader.Data,
  		Cap: stringHeader.Len,
  		Len: stringHeader.Len,
  	}
  	return *(*[]byte)(unsafe.Pointer(sliceHeader))
  }
  