diff options
Diffstat (limited to 'vendor/github.com/modern-go/reflect2/reflect2.go')
-rw-r--r-- | vendor/github.com/modern-go/reflect2/reflect2.go | 300 |
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 @@ | |||
1 | package reflect2 | ||
2 | |||
3 | import ( | ||
4 | "reflect" | ||
5 | "runtime" | ||
6 | "sync" | ||
7 | "unsafe" | ||
8 | ) | ||
9 | |||
10 | type 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 | |||
37 | type 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 | |||
46 | type ArrayType interface { | ||
47 | ListType | ||
48 | Len() int | ||
49 | } | ||
50 | |||
51 | type 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 | |||
67 | type 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 | |||
76 | type 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 | |||
90 | type 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 | |||
105 | type MapIterator interface { | ||
106 | HasNext() bool | ||
107 | Next() (key interface{}, elem interface{}) | ||
108 | UnsafeNext() (key unsafe.Pointer, elem unsafe.Pointer) | ||
109 | } | ||
110 | |||
111 | type PtrType interface { | ||
112 | Type | ||
113 | Elem() Type | ||
114 | } | ||
115 | |||
116 | type InterfaceType interface { | ||
117 | NumMethod() int | ||
118 | } | ||
119 | |||
120 | type Config struct { | ||
121 | UseSafeImplementation bool | ||
122 | } | ||
123 | |||
124 | type API interface { | ||
125 | TypeOf(obj interface{}) Type | ||
126 | Type2(type1 reflect.Type) Type | ||
127 | } | ||
128 | |||
129 | var ConfigUnsafe = Config{UseSafeImplementation: false}.Froze() | ||
130 | var ConfigSafe = Config{UseSafeImplementation: true}.Froze() | ||
131 | |||
132 | type frozenConfig struct { | ||
133 | useSafeImplementation bool | ||
134 | cache *sync.Map | ||
135 | } | ||
136 | |||
137 | func (cfg Config) Froze() *frozenConfig { | ||
138 | return &frozenConfig{ | ||
139 | useSafeImplementation: cfg.UseSafeImplementation, | ||
140 | cache: new(sync.Map), | ||
141 | } | ||
142 | } | ||
143 | |||
144 | func (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 | |||
153 | func (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 | |||
167 | func (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 | |||
211 | func TypeOf(obj interface{}) Type { | ||
212 | return ConfigUnsafe.TypeOf(obj) | ||
213 | } | ||
214 | |||
215 | func TypeOfPtr(obj interface{}) PtrType { | ||
216 | return TypeOf(obj).(PtrType) | ||
217 | } | ||
218 | |||
219 | func Type2(type1 reflect.Type) Type { | ||
220 | if type1 == nil { | ||
221 | return nil | ||
222 | } | ||
223 | return ConfigUnsafe.Type2(type1) | ||
224 | } | ||
225 | |||
226 | func PtrTo(typ Type) Type { | ||
227 | return Type2(reflect.PtrTo(typ.Type1())) | ||
228 | } | ||
229 | |||
230 | func PtrOf(obj interface{}) unsafe.Pointer { | ||
231 | return unpackEFace(obj).data | ||
232 | } | ||
233 | |||
234 | func RTypeOf(obj interface{}) uintptr { | ||
235 | return uintptr(unpackEFace(obj).rtype) | ||
236 | } | ||
237 | |||
238 | func IsNil(obj interface{}) bool { | ||
239 | if obj == nil { | ||
240 | return true | ||
241 | } | ||
242 | return unpackEFace(obj).data == nil | ||
243 | } | ||
244 | |||
245 | func 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 | |||
253 | func 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 | |||
261 | func 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 | ||
286 | func NoEscape(p unsafe.Pointer) unsafe.Pointer { | ||
287 | x := uintptr(p) | ||
288 | return unsafe.Pointer(x ^ 0) | ||
289 | } | ||
290 | |||
291 | func 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 | } | ||