reflect2.go 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. package reflect2
  2. import (
  3. "reflect"
  4. "unsafe"
  5. "github.com/modern-go/concurrent"
  6. )
  7. type Type interface {
  8. Kind() reflect.Kind
  9. // New return pointer to data of this type
  10. New() interface{}
  11. // UnsafeNew return the allocated space pointed by unsafe.Pointer
  12. UnsafeNew() unsafe.Pointer
  13. // PackEFace cast a unsafe pointer to object represented pointer
  14. PackEFace(ptr unsafe.Pointer) interface{}
  15. // Indirect dereference object represented pointer to this type
  16. Indirect(obj interface{}) interface{}
  17. // UnsafeIndirect dereference pointer to this type
  18. UnsafeIndirect(ptr unsafe.Pointer) interface{}
  19. // Type1 returns reflect.Type
  20. Type1() reflect.Type
  21. Implements(thatType Type) bool
  22. String() string
  23. RType() uintptr
  24. // interface{} of this type has pointer like behavior
  25. LikePtr() bool
  26. IsNullable() bool
  27. IsNil(obj interface{}) bool
  28. UnsafeIsNil(ptr unsafe.Pointer) bool
  29. Set(obj interface{}, val interface{})
  30. UnsafeSet(ptr unsafe.Pointer, val unsafe.Pointer)
  31. AssignableTo(anotherType Type) bool
  32. }
  33. type ListType interface {
  34. Type
  35. Elem() Type
  36. SetIndex(obj interface{}, index int, elem interface{})
  37. UnsafeSetIndex(obj unsafe.Pointer, index int, elem unsafe.Pointer)
  38. GetIndex(obj interface{}, index int) interface{}
  39. UnsafeGetIndex(obj unsafe.Pointer, index int) unsafe.Pointer
  40. }
  41. type ArrayType interface {
  42. ListType
  43. Len() int
  44. }
  45. type SliceType interface {
  46. ListType
  47. MakeSlice(length int, cap int) interface{}
  48. UnsafeMakeSlice(length int, cap int) unsafe.Pointer
  49. Grow(obj interface{}, newLength int)
  50. UnsafeGrow(ptr unsafe.Pointer, newLength int)
  51. Append(obj interface{}, elem interface{})
  52. UnsafeAppend(obj unsafe.Pointer, elem unsafe.Pointer)
  53. LengthOf(obj interface{}) int
  54. UnsafeLengthOf(ptr unsafe.Pointer) int
  55. SetNil(obj interface{})
  56. UnsafeSetNil(ptr unsafe.Pointer)
  57. Cap(obj interface{}) int
  58. UnsafeCap(ptr unsafe.Pointer) int
  59. }
  60. type StructType interface {
  61. Type
  62. NumField() int
  63. Field(i int) StructField
  64. FieldByName(name string) StructField
  65. FieldByIndex(index []int) StructField
  66. FieldByNameFunc(match func(string) bool) StructField
  67. }
  68. type StructField interface {
  69. Offset() uintptr
  70. Name() string
  71. PkgPath() string
  72. Type() Type
  73. Tag() reflect.StructTag
  74. Index() []int
  75. Anonymous() bool
  76. Set(obj interface{}, value interface{})
  77. UnsafeSet(obj unsafe.Pointer, value unsafe.Pointer)
  78. Get(obj interface{}) interface{}
  79. UnsafeGet(obj unsafe.Pointer) unsafe.Pointer
  80. }
  81. type MapType interface {
  82. Type
  83. Key() Type
  84. Elem() Type
  85. MakeMap(cap int) interface{}
  86. UnsafeMakeMap(cap int) unsafe.Pointer
  87. SetIndex(obj interface{}, key interface{}, elem interface{})
  88. UnsafeSetIndex(obj unsafe.Pointer, key unsafe.Pointer, elem unsafe.Pointer)
  89. TryGetIndex(obj interface{}, key interface{}) (interface{}, bool)
  90. GetIndex(obj interface{}, key interface{}) interface{}
  91. UnsafeGetIndex(obj unsafe.Pointer, key unsafe.Pointer) unsafe.Pointer
  92. Iterate(obj interface{}) MapIterator
  93. UnsafeIterate(obj unsafe.Pointer) MapIterator
  94. }
  95. type MapIterator interface {
  96. HasNext() bool
  97. Next() (key interface{}, elem interface{})
  98. UnsafeNext() (key unsafe.Pointer, elem unsafe.Pointer)
  99. }
  100. type PtrType interface {
  101. Type
  102. Elem() Type
  103. }
  104. type InterfaceType interface {
  105. NumMethod() int
  106. }
  107. type Config struct {
  108. UseSafeImplementation bool
  109. }
  110. type API interface {
  111. TypeOf(obj interface{}) Type
  112. Type2(type1 reflect.Type) Type
  113. }
  114. var ConfigUnsafe = Config{UseSafeImplementation: false}.Froze()
  115. var ConfigSafe = Config{UseSafeImplementation: true}.Froze()
  116. type frozenConfig struct {
  117. useSafeImplementation bool
  118. cache *concurrent.Map
  119. }
  120. func (cfg Config) Froze() *frozenConfig {
  121. return &frozenConfig{
  122. useSafeImplementation: cfg.UseSafeImplementation,
  123. cache: concurrent.NewMap(),
  124. }
  125. }
  126. func (cfg *frozenConfig) TypeOf(obj interface{}) Type {
  127. cacheKey := uintptr(unpackEFace(obj).rtype)
  128. typeObj, found := cfg.cache.Load(cacheKey)
  129. if found {
  130. return typeObj.(Type)
  131. }
  132. return cfg.Type2(reflect.TypeOf(obj))
  133. }
  134. func (cfg *frozenConfig) Type2(type1 reflect.Type) Type {
  135. cacheKey := uintptr(unpackEFace(type1).data)
  136. typeObj, found := cfg.cache.Load(cacheKey)
  137. if found {
  138. return typeObj.(Type)
  139. }
  140. type2 := cfg.wrapType(type1)
  141. cfg.cache.Store(cacheKey, type2)
  142. return type2
  143. }
  144. func (cfg *frozenConfig) wrapType(type1 reflect.Type) Type {
  145. safeType := safeType{Type: type1, cfg: cfg}
  146. switch type1.Kind() {
  147. case reflect.Struct:
  148. if cfg.useSafeImplementation {
  149. return &safeStructType{safeType}
  150. }
  151. return newUnsafeStructType(cfg, type1)
  152. case reflect.Array:
  153. if cfg.useSafeImplementation {
  154. return &safeSliceType{safeType}
  155. }
  156. return newUnsafeArrayType(cfg, type1)
  157. case reflect.Slice:
  158. if cfg.useSafeImplementation {
  159. return &safeSliceType{safeType}
  160. }
  161. return newUnsafeSliceType(cfg, type1)
  162. case reflect.Map:
  163. if cfg.useSafeImplementation {
  164. return &safeMapType{safeType}
  165. }
  166. return newUnsafeMapType(cfg, type1)
  167. case reflect.Ptr, reflect.Chan, reflect.Func:
  168. if cfg.useSafeImplementation {
  169. return &safeMapType{safeType}
  170. }
  171. return newUnsafePtrType(cfg, type1)
  172. case reflect.Interface:
  173. if cfg.useSafeImplementation {
  174. return &safeMapType{safeType}
  175. }
  176. if type1.NumMethod() == 0 {
  177. return newUnsafeEFaceType(cfg, type1)
  178. }
  179. return newUnsafeIFaceType(cfg, type1)
  180. default:
  181. if cfg.useSafeImplementation {
  182. return &safeType
  183. }
  184. return newUnsafeType(cfg, type1)
  185. }
  186. }
  187. func TypeOf(obj interface{}) Type {
  188. return ConfigUnsafe.TypeOf(obj)
  189. }
  190. func TypeOfPtr(obj interface{}) PtrType {
  191. return TypeOf(obj).(PtrType)
  192. }
  193. func Type2(type1 reflect.Type) Type {
  194. return ConfigUnsafe.Type2(type1)
  195. }
  196. func PtrTo(typ Type) Type {
  197. return Type2(reflect.PtrTo(typ.Type1()))
  198. }
  199. func PtrOf(obj interface{}) unsafe.Pointer {
  200. return unpackEFace(obj).data
  201. }
  202. func RTypeOf(obj interface{}) uintptr {
  203. return uintptr(unpackEFace(obj).rtype)
  204. }
  205. func IsNil(obj interface{}) bool {
  206. if obj == nil {
  207. return true
  208. }
  209. return unpackEFace(obj).data == nil
  210. }
  211. func IsNullable(kind reflect.Kind) bool {
  212. switch kind {
  213. case reflect.Ptr, reflect.Map, reflect.Chan, reflect.Func, reflect.Slice, reflect.Interface:
  214. return true
  215. }
  216. return false
  217. }
  218. func likePtrKind(kind reflect.Kind) bool {
  219. switch kind {
  220. case reflect.Ptr, reflect.Map, reflect.Chan, reflect.Func:
  221. return true
  222. }
  223. return false
  224. }
  225. func likePtrType(typ reflect.Type) bool {
  226. if likePtrKind(typ.Kind()) {
  227. return true
  228. }
  229. if typ.Kind() == reflect.Struct {
  230. if typ.NumField() != 1 {
  231. return false
  232. }
  233. return likePtrType(typ.Field(0).Type)
  234. }
  235. if typ.Kind() == reflect.Array {
  236. if typ.Len() != 1 {
  237. return false
  238. }
  239. return likePtrType(typ.Elem())
  240. }
  241. return false
  242. }
  243. // NoEscape hides a pointer from escape analysis. noescape is
  244. // the identity function but escape analysis doesn't think the
  245. // output depends on the input. noescape is inlined and currently
  246. // compiles down to zero instructions.
  247. // USE CAREFULLY!
  248. //go:nosplit
  249. func NoEscape(p unsafe.Pointer) unsafe.Pointer {
  250. x := uintptr(p)
  251. return unsafe.Pointer(x ^ 0)
  252. }