Code refactoring for bpa operator
[icn.git] / cmd / bpa-operator / vendor / github.com / modern-go / reflect2 / reflect2.go
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 }