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