reflect2.go 7.1 KB

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