1
2
3
4
5
6
7 package reflectlite
8
9 import (
10 "internal/abi"
11 "unsafe"
12 )
13
14
15
16
17
18
19
20
21
22
23
24
25 type Type interface {
26
27
28
29
30 Name() string
31
32
33
34
35
36
37 PkgPath() string
38
39
40
41 Size() uintptr
42
43
44 Kind() Kind
45
46
47 Implements(u Type) bool
48
49
50 AssignableTo(u Type) bool
51
52
53 Comparable() bool
54
55
56
57
58
59
60 String() string
61
62
63
64 Elem() Type
65
66 common() *abi.Type
67 uncommon() *uncommonType
68 }
69
70
75
76
77
78 type Kind = abi.Kind
79
80 const Ptr = abi.Pointer
81
82 const (
83
84 Interface = abi.Interface
85 Slice = abi.Slice
86 String = abi.String
87 Struct = abi.Struct
88 )
89
90 type nameOff = abi.NameOff
91 type typeOff = abi.TypeOff
92 type textOff = abi.TextOff
93
94 type rtype struct {
95 *abi.Type
96 }
97
98
99
100
101
102 type uncommonType = abi.UncommonType
103
104
105 type arrayType = abi.ArrayType
106
107
108 type chanType = abi.ChanType
109
110 type funcType = abi.FuncType
111
112 type interfaceType = abi.InterfaceType
113
114
115 type ptrType = abi.PtrType
116
117
118 type sliceType = abi.SliceType
119
120
121 type structType = abi.StructType
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146 type name struct {
147 bytes *byte
148 }
149
150 func (n name) data(off int, whySafe string) *byte {
151 return (*byte)(add(unsafe.Pointer(n.bytes), uintptr(off), whySafe))
152 }
153
154 func (n name) isExported() bool {
155 return (*n.bytes)&(1<<0) != 0
156 }
157
158 func (n name) hasTag() bool {
159 return (*n.bytes)&(1<<1) != 0
160 }
161
162 func (n name) embedded() bool {
163 return (*n.bytes)&(1<<3) != 0
164 }
165
166
167
168 func (n name) readVarint(off int) (int, int) {
169 v := 0
170 for i := 0; ; i++ {
171 x := *n.data(off+i, "read varint")
172 v += int(x&0x7f) << (7 * i)
173 if x&0x80 == 0 {
174 return i + 1, v
175 }
176 }
177 }
178
179 func (n name) name() string {
180 if n.bytes == nil {
181 return ""
182 }
183 i, l := n.readVarint(1)
184 return unsafe.String(n.data(1+i, "non-empty string"), l)
185 }
186
187 func (n name) tag() string {
188 if !n.hasTag() {
189 return ""
190 }
191 i, l := n.readVarint(1)
192 i2, l2 := n.readVarint(1 + i + l)
193 return unsafe.String(n.data(1+i+l+i2, "non-empty string"), l2)
194 }
195
196 func pkgPath(n abi.Name) string {
197 if n.Bytes == nil || *n.DataChecked(0, "name flag field")&(1<<2) == 0 {
198 return ""
199 }
200 i, l := n.ReadVarint(1)
201 off := 1 + i + l
202 if n.HasTag() {
203 i2, l2 := n.ReadVarint(off)
204 off += i2 + l2
205 }
206 var nameOff int32
207
208
209 copy((*[4]byte)(unsafe.Pointer(&nameOff))[:], (*[4]byte)(unsafe.Pointer(n.DataChecked(off, "name offset field")))[:])
210 pkgPathName := name{(*byte)(resolveTypeOff(unsafe.Pointer(n.Bytes), nameOff))}
211 return pkgPathName.name()
212 }
213
214
218
219
220
221
222
223
224 func resolveNameOff(ptrInModule unsafe.Pointer, off int32) unsafe.Pointer
225
226
227
228
229
230
231 func resolveTypeOff(rtype unsafe.Pointer, off int32) unsafe.Pointer
232
233 func (t rtype) nameOff(off nameOff) abi.Name {
234 return abi.Name{Bytes: (*byte)(resolveNameOff(unsafe.Pointer(t.Type), int32(off)))}
235 }
236
237 func (t rtype) typeOff(off typeOff) *abi.Type {
238 return (*abi.Type)(resolveTypeOff(unsafe.Pointer(t.Type), int32(off)))
239 }
240
241 func (t rtype) uncommon() *uncommonType {
242 return t.Uncommon()
243 }
244
245 func (t rtype) String() string {
246 s := t.nameOff(t.Str).Name()
247 if t.TFlag&abi.TFlagExtraStar != 0 {
248 return s[1:]
249 }
250 return s
251 }
252
253 func (t rtype) common() *abi.Type { return t.Type }
254
255 func (t rtype) exportedMethods() []abi.Method {
256 ut := t.uncommon()
257 if ut == nil {
258 return nil
259 }
260 return ut.ExportedMethods()
261 }
262
263 func (t rtype) NumMethod() int {
264 tt := t.Type.InterfaceType()
265 if tt != nil {
266 return tt.NumMethod()
267 }
268 return len(t.exportedMethods())
269 }
270
271 func (t rtype) PkgPath() string {
272 if t.TFlag&abi.TFlagNamed == 0 {
273 return ""
274 }
275 ut := t.uncommon()
276 if ut == nil {
277 return ""
278 }
279 return t.nameOff(ut.PkgPath).Name()
280 }
281
282 func (t rtype) Name() string {
283 if !t.HasName() {
284 return ""
285 }
286 s := t.String()
287 i := len(s) - 1
288 sqBrackets := 0
289 for i >= 0 && (s[i] != '.' || sqBrackets != 0) {
290 switch s[i] {
291 case ']':
292 sqBrackets++
293 case '[':
294 sqBrackets--
295 }
296 i--
297 }
298 return s[i+1:]
299 }
300
301 func toRType(t *abi.Type) rtype {
302 return rtype{t}
303 }
304
305 func elem(t *abi.Type) *abi.Type {
306 et := t.Elem()
307 if et != nil {
308 return et
309 }
310 panic("reflect: Elem of invalid type " + toRType(t).String())
311 }
312
313 func (t rtype) Elem() Type {
314 return toType(elem(t.common()))
315 }
316
317 func (t rtype) In(i int) Type {
318 tt := t.Type.FuncType()
319 if tt == nil {
320 panic("reflect: In of non-func type")
321 }
322 return toType(tt.InSlice()[i])
323 }
324
325 func (t rtype) Key() Type {
326 tt := t.Type.MapType()
327 if tt == nil {
328 panic("reflect: Key of non-map type")
329 }
330 return toType(tt.Key)
331 }
332
333 func (t rtype) Len() int {
334 tt := t.Type.ArrayType()
335 if tt == nil {
336 panic("reflect: Len of non-array type")
337 }
338 return int(tt.Len)
339 }
340
341 func (t rtype) NumField() int {
342 tt := t.Type.StructType()
343 if tt == nil {
344 panic("reflect: NumField of non-struct type")
345 }
346 return len(tt.Fields)
347 }
348
349 func (t rtype) NumIn() int {
350 tt := t.Type.FuncType()
351 if tt == nil {
352 panic("reflect: NumIn of non-func type")
353 }
354 return int(tt.InCount)
355 }
356
357 func (t rtype) NumOut() int {
358 tt := t.Type.FuncType()
359 if tt == nil {
360 panic("reflect: NumOut of non-func type")
361 }
362 return tt.NumOut()
363 }
364
365 func (t rtype) Out(i int) Type {
366 tt := t.Type.FuncType()
367 if tt == nil {
368 panic("reflect: Out of non-func type")
369 }
370 return toType(tt.OutSlice()[i])
371 }
372
373
374
375
376
377
378
379
380 func add(p unsafe.Pointer, x uintptr, whySafe string) unsafe.Pointer {
381 return unsafe.Pointer(uintptr(p) + x)
382 }
383
384
385
386 func TypeOf(i any) Type {
387 return toType(abi.TypeOf(i))
388 }
389
390 func (t rtype) Implements(u Type) bool {
391 if u == nil {
392 panic("reflect: nil type passed to Type.Implements")
393 }
394 if u.Kind() != Interface {
395 panic("reflect: non-interface type passed to Type.Implements")
396 }
397 return implements(u.common(), t.common())
398 }
399
400 func (t rtype) AssignableTo(u Type) bool {
401 if u == nil {
402 panic("reflect: nil type passed to Type.AssignableTo")
403 }
404 uu := u.common()
405 tt := t.common()
406 return directlyAssignable(uu, tt) || implements(uu, tt)
407 }
408
409 func (t rtype) Comparable() bool {
410 return t.Equal != nil
411 }
412
413
414 func implements(T, V *abi.Type) bool {
415 t := T.InterfaceType()
416 if t == nil {
417 return false
418 }
419 if len(t.Methods) == 0 {
420 return true
421 }
422 rT := toRType(T)
423 rV := toRType(V)
424
425
426
427
428
429
430
431
432
433
434
435
436
437 if V.Kind() == Interface {
438 v := (*interfaceType)(unsafe.Pointer(V))
439 i := 0
440 for j := 0; j < len(v.Methods); j++ {
441 tm := &t.Methods[i]
442 tmName := rT.nameOff(tm.Name)
443 vm := &v.Methods[j]
444 vmName := rV.nameOff(vm.Name)
445 if vmName.Name() == tmName.Name() && rV.typeOff(vm.Typ) == rT.typeOff(tm.Typ) {
446 if !tmName.IsExported() {
447 tmPkgPath := pkgPath(tmName)
448 if tmPkgPath == "" {
449 tmPkgPath = t.PkgPath.Name()
450 }
451 vmPkgPath := pkgPath(vmName)
452 if vmPkgPath == "" {
453 vmPkgPath = v.PkgPath.Name()
454 }
455 if tmPkgPath != vmPkgPath {
456 continue
457 }
458 }
459 if i++; i >= len(t.Methods) {
460 return true
461 }
462 }
463 }
464 return false
465 }
466
467 v := V.Uncommon()
468 if v == nil {
469 return false
470 }
471 i := 0
472 vmethods := v.Methods()
473 for j := 0; j < int(v.Mcount); j++ {
474 tm := &t.Methods[i]
475 tmName := rT.nameOff(tm.Name)
476 vm := vmethods[j]
477 vmName := rV.nameOff(vm.Name)
478 if vmName.Name() == tmName.Name() && rV.typeOff(vm.Mtyp) == rT.typeOff(tm.Typ) {
479 if !tmName.IsExported() {
480 tmPkgPath := pkgPath(tmName)
481 if tmPkgPath == "" {
482 tmPkgPath = t.PkgPath.Name()
483 }
484 vmPkgPath := pkgPath(vmName)
485 if vmPkgPath == "" {
486 vmPkgPath = rV.nameOff(v.PkgPath).Name()
487 }
488 if tmPkgPath != vmPkgPath {
489 continue
490 }
491 }
492 if i++; i >= len(t.Methods) {
493 return true
494 }
495 }
496 }
497 return false
498 }
499
500
501
502
503
504
505 func directlyAssignable(T, V *abi.Type) bool {
506
507 if T == V {
508 return true
509 }
510
511
512
513 if T.HasName() && V.HasName() || T.Kind() != V.Kind() {
514 return false
515 }
516
517
518 return haveIdenticalUnderlyingType(T, V, true)
519 }
520
521 func haveIdenticalType(T, V *abi.Type, cmpTags bool) bool {
522 if cmpTags {
523 return T == V
524 }
525
526 if toRType(T).Name() != toRType(V).Name() || T.Kind() != V.Kind() {
527 return false
528 }
529
530 return haveIdenticalUnderlyingType(T, V, false)
531 }
532
533 func haveIdenticalUnderlyingType(T, V *abi.Type, cmpTags bool) bool {
534 if T == V {
535 return true
536 }
537
538 kind := T.Kind()
539 if kind != V.Kind() {
540 return false
541 }
542
543
544
545 if abi.Bool <= kind && kind <= abi.Complex128 || kind == abi.String || kind == abi.UnsafePointer {
546 return true
547 }
548
549
550 switch kind {
551 case abi.Array:
552 return T.Len() == V.Len() && haveIdenticalType(T.Elem(), V.Elem(), cmpTags)
553
554 case abi.Chan:
555
556
557
558 if V.ChanDir() == abi.BothDir && haveIdenticalType(T.Elem(), V.Elem(), cmpTags) {
559 return true
560 }
561
562
563 return V.ChanDir() == T.ChanDir() && haveIdenticalType(T.Elem(), V.Elem(), cmpTags)
564
565 case abi.Func:
566 t := (*funcType)(unsafe.Pointer(T))
567 v := (*funcType)(unsafe.Pointer(V))
568 if t.OutCount != v.OutCount || t.InCount != v.InCount {
569 return false
570 }
571 for i := 0; i < t.NumIn(); i++ {
572 if !haveIdenticalType(t.In(i), v.In(i), cmpTags) {
573 return false
574 }
575 }
576 for i := 0; i < t.NumOut(); i++ {
577 if !haveIdenticalType(t.Out(i), v.Out(i), cmpTags) {
578 return false
579 }
580 }
581 return true
582
583 case Interface:
584 t := (*interfaceType)(unsafe.Pointer(T))
585 v := (*interfaceType)(unsafe.Pointer(V))
586 if len(t.Methods) == 0 && len(v.Methods) == 0 {
587 return true
588 }
589
590
591 return false
592
593 case abi.Map:
594 return haveIdenticalType(T.Key(), V.Key(), cmpTags) && haveIdenticalType(T.Elem(), V.Elem(), cmpTags)
595
596 case Ptr, abi.Slice:
597 return haveIdenticalType(T.Elem(), V.Elem(), cmpTags)
598
599 case abi.Struct:
600 t := (*structType)(unsafe.Pointer(T))
601 v := (*structType)(unsafe.Pointer(V))
602 if len(t.Fields) != len(v.Fields) {
603 return false
604 }
605 if t.PkgPath.Name() != v.PkgPath.Name() {
606 return false
607 }
608 for i := range t.Fields {
609 tf := &t.Fields[i]
610 vf := &v.Fields[i]
611 if tf.Name.Name() != vf.Name.Name() {
612 return false
613 }
614 if !haveIdenticalType(tf.Typ, vf.Typ, cmpTags) {
615 return false
616 }
617 if cmpTags && tf.Name.Tag() != vf.Name.Tag() {
618 return false
619 }
620 if tf.Offset != vf.Offset {
621 return false
622 }
623 if tf.Embedded() != vf.Embedded() {
624 return false
625 }
626 }
627 return true
628 }
629
630 return false
631 }
632
633
634
635
636
637
638 func toType(t *abi.Type) Type {
639 if t == nil {
640 return nil
641 }
642 return toRType(t)
643 }
644
View as plain text