1
2
3
4
5
6
7 package reflectlite
8
9 import (
10 "internal/unsafeheader"
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() *rtype
67 uncommon() *uncommonType
68 }
69
70
75
76
77
78 type Kind uint
79
80 const (
81 Invalid Kind = iota
82 Bool
83 Int
84 Int8
85 Int16
86 Int32
87 Int64
88 Uint
89 Uint8
90 Uint16
91 Uint32
92 Uint64
93 Uintptr
94 Float32
95 Float64
96 Complex64
97 Complex128
98 Array
99 Chan
100 Func
101 Interface
102 Map
103 Pointer
104 Slice
105 String
106 Struct
107 UnsafePointer
108 )
109
110 const Ptr = Pointer
111
112
113
114
115
116
117
118
119 type tflag uint8
120
121 const (
122
123
124
125
126
127
128
129
130
131
132
133 tflagUncommon tflag = 1 << 0
134
135
136
137
138
139 tflagExtraStar tflag = 1 << 1
140
141
142 tflagNamed tflag = 1 << 2
143
144
145
146 tflagRegularMemory tflag = 1 << 3
147 )
148
149
150
151
152
153 type rtype struct {
154 size uintptr
155 ptrdata uintptr
156 hash uint32
157 tflag tflag
158 align uint8
159 fieldAlign uint8
160 kind uint8
161
162
163 equal func(unsafe.Pointer, unsafe.Pointer) bool
164 gcdata *byte
165 str nameOff
166 ptrToThis typeOff
167 }
168
169
170 type method struct {
171 name nameOff
172 mtyp typeOff
173 ifn textOff
174 tfn textOff
175 }
176
177
178
179
180
181 type uncommonType struct {
182 pkgPath nameOff
183 mcount uint16
184 xcount uint16
185 moff uint32
186 _ uint32
187 }
188
189
190 type chanDir int
191
192 const (
193 recvDir chanDir = 1 << iota
194 sendDir
195 bothDir = recvDir | sendDir
196 )
197
198
199 type arrayType struct {
200 rtype
201 elem *rtype
202 slice *rtype
203 len uintptr
204 }
205
206
207 type chanType struct {
208 rtype
209 elem *rtype
210 dir uintptr
211 }
212
213
214
215
216
217
218
219
220
221
222
223
224 type funcType struct {
225 rtype
226 inCount uint16
227 outCount uint16
228 }
229
230
231 type imethod struct {
232 name nameOff
233 typ typeOff
234 }
235
236
237 type interfaceType struct {
238 rtype
239 pkgPath name
240 methods []imethod
241 }
242
243
244 type mapType struct {
245 rtype
246 key *rtype
247 elem *rtype
248 bucket *rtype
249
250 hasher func(unsafe.Pointer, uintptr) uintptr
251 keysize uint8
252 valuesize uint8
253 bucketsize uint16
254 flags uint32
255 }
256
257
258 type ptrType struct {
259 rtype
260 elem *rtype
261 }
262
263
264 type sliceType struct {
265 rtype
266 elem *rtype
267 }
268
269
270 type structField struct {
271 name name
272 typ *rtype
273 offsetEmbed uintptr
274 }
275
276 func (f *structField) offset() uintptr {
277 return f.offsetEmbed >> 1
278 }
279
280 func (f *structField) embedded() bool {
281 return f.offsetEmbed&1 != 0
282 }
283
284
285 type structType struct {
286 rtype
287 pkgPath name
288 fields []structField
289 }
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314 type name struct {
315 bytes *byte
316 }
317
318 func (n name) data(off int, whySafe string) *byte {
319 return (*byte)(add(unsafe.Pointer(n.bytes), uintptr(off), whySafe))
320 }
321
322 func (n name) isExported() bool {
323 return (*n.bytes)&(1<<0) != 0
324 }
325
326 func (n name) hasTag() bool {
327 return (*n.bytes)&(1<<1) != 0
328 }
329
330
331
332 func (n name) readVarint(off int) (int, int) {
333 v := 0
334 for i := 0; ; i++ {
335 x := *n.data(off+i, "read varint")
336 v += int(x&0x7f) << (7 * i)
337 if x&0x80 == 0 {
338 return i + 1, v
339 }
340 }
341 }
342
343 func (n name) name() (s string) {
344 if n.bytes == nil {
345 return
346 }
347 i, l := n.readVarint(1)
348 hdr := (*unsafeheader.String)(unsafe.Pointer(&s))
349 hdr.Data = unsafe.Pointer(n.data(1+i, "non-empty string"))
350 hdr.Len = l
351 return
352 }
353
354 func (n name) tag() (s string) {
355 if !n.hasTag() {
356 return ""
357 }
358 i, l := n.readVarint(1)
359 i2, l2 := n.readVarint(1 + i + l)
360 hdr := (*unsafeheader.String)(unsafe.Pointer(&s))
361 hdr.Data = unsafe.Pointer(n.data(1+i+l+i2, "non-empty string"))
362 hdr.Len = l2
363 return
364 }
365
366 func (n name) pkgPath() string {
367 if n.bytes == nil || *n.data(0, "name flag field")&(1<<2) == 0 {
368 return ""
369 }
370 i, l := n.readVarint(1)
371 off := 1 + i + l
372 if n.hasTag() {
373 i2, l2 := n.readVarint(off)
374 off += i2 + l2
375 }
376 var nameOff int32
377
378
379 copy((*[4]byte)(unsafe.Pointer(&nameOff))[:], (*[4]byte)(unsafe.Pointer(n.data(off, "name offset field")))[:])
380 pkgPathName := name{(*byte)(resolveTypeOff(unsafe.Pointer(n.bytes), nameOff))}
381 return pkgPathName.name()
382 }
383
384
388
389 const (
390 kindDirectIface = 1 << 5
391 kindGCProg = 1 << 6
392 kindMask = (1 << 5) - 1
393 )
394
395
396 func (k Kind) String() string {
397 if int(k) < len(kindNames) {
398 return kindNames[k]
399 }
400 return kindNames[0]
401 }
402
403 var kindNames = []string{
404 Invalid: "invalid",
405 Bool: "bool",
406 Int: "int",
407 Int8: "int8",
408 Int16: "int16",
409 Int32: "int32",
410 Int64: "int64",
411 Uint: "uint",
412 Uint8: "uint8",
413 Uint16: "uint16",
414 Uint32: "uint32",
415 Uint64: "uint64",
416 Uintptr: "uintptr",
417 Float32: "float32",
418 Float64: "float64",
419 Complex64: "complex64",
420 Complex128: "complex128",
421 Array: "array",
422 Chan: "chan",
423 Func: "func",
424 Interface: "interface",
425 Map: "map",
426 Ptr: "ptr",
427 Slice: "slice",
428 String: "string",
429 Struct: "struct",
430 UnsafePointer: "unsafe.Pointer",
431 }
432
433 func (t *uncommonType) methods() []method {
434 if t.mcount == 0 {
435 return nil
436 }
437 return (*[1 << 16]method)(add(unsafe.Pointer(t), uintptr(t.moff), "t.mcount > 0"))[:t.mcount:t.mcount]
438 }
439
440 func (t *uncommonType) exportedMethods() []method {
441 if t.xcount == 0 {
442 return nil
443 }
444 return (*[1 << 16]method)(add(unsafe.Pointer(t), uintptr(t.moff), "t.xcount > 0"))[:t.xcount:t.xcount]
445 }
446
447
448
449
450 func resolveNameOff(ptrInModule unsafe.Pointer, off int32) unsafe.Pointer
451
452
453
454
455 func resolveTypeOff(rtype unsafe.Pointer, off int32) unsafe.Pointer
456
457 type nameOff int32
458 type typeOff int32
459 type textOff int32
460
461 func (t *rtype) nameOff(off nameOff) name {
462 return name{(*byte)(resolveNameOff(unsafe.Pointer(t), int32(off)))}
463 }
464
465 func (t *rtype) typeOff(off typeOff) *rtype {
466 return (*rtype)(resolveTypeOff(unsafe.Pointer(t), int32(off)))
467 }
468
469 func (t *rtype) uncommon() *uncommonType {
470 if t.tflag&tflagUncommon == 0 {
471 return nil
472 }
473 switch t.Kind() {
474 case Struct:
475 return &(*structTypeUncommon)(unsafe.Pointer(t)).u
476 case Ptr:
477 type u struct {
478 ptrType
479 u uncommonType
480 }
481 return &(*u)(unsafe.Pointer(t)).u
482 case Func:
483 type u struct {
484 funcType
485 u uncommonType
486 }
487 return &(*u)(unsafe.Pointer(t)).u
488 case Slice:
489 type u struct {
490 sliceType
491 u uncommonType
492 }
493 return &(*u)(unsafe.Pointer(t)).u
494 case Array:
495 type u struct {
496 arrayType
497 u uncommonType
498 }
499 return &(*u)(unsafe.Pointer(t)).u
500 case Chan:
501 type u struct {
502 chanType
503 u uncommonType
504 }
505 return &(*u)(unsafe.Pointer(t)).u
506 case Map:
507 type u struct {
508 mapType
509 u uncommonType
510 }
511 return &(*u)(unsafe.Pointer(t)).u
512 case Interface:
513 type u struct {
514 interfaceType
515 u uncommonType
516 }
517 return &(*u)(unsafe.Pointer(t)).u
518 default:
519 type u struct {
520 rtype
521 u uncommonType
522 }
523 return &(*u)(unsafe.Pointer(t)).u
524 }
525 }
526
527 func (t *rtype) String() string {
528 s := t.nameOff(t.str).name()
529 if t.tflag&tflagExtraStar != 0 {
530 return s[1:]
531 }
532 return s
533 }
534
535 func (t *rtype) Size() uintptr { return t.size }
536
537 func (t *rtype) Kind() Kind { return Kind(t.kind & kindMask) }
538
539 func (t *rtype) pointers() bool { return t.ptrdata != 0 }
540
541 func (t *rtype) common() *rtype { return t }
542
543 func (t *rtype) exportedMethods() []method {
544 ut := t.uncommon()
545 if ut == nil {
546 return nil
547 }
548 return ut.exportedMethods()
549 }
550
551 func (t *rtype) NumMethod() int {
552 if t.Kind() == Interface {
553 tt := (*interfaceType)(unsafe.Pointer(t))
554 return tt.NumMethod()
555 }
556 return len(t.exportedMethods())
557 }
558
559 func (t *rtype) PkgPath() string {
560 if t.tflag&tflagNamed == 0 {
561 return ""
562 }
563 ut := t.uncommon()
564 if ut == nil {
565 return ""
566 }
567 return t.nameOff(ut.pkgPath).name()
568 }
569
570 func (t *rtype) hasName() bool {
571 return t.tflag&tflagNamed != 0
572 }
573
574 func (t *rtype) Name() string {
575 if !t.hasName() {
576 return ""
577 }
578 s := t.String()
579 i := len(s) - 1
580 for i >= 0 && s[i] != '.' {
581 i--
582 }
583 return s[i+1:]
584 }
585
586 func (t *rtype) chanDir() chanDir {
587 if t.Kind() != Chan {
588 panic("reflect: chanDir of non-chan type")
589 }
590 tt := (*chanType)(unsafe.Pointer(t))
591 return chanDir(tt.dir)
592 }
593
594 func (t *rtype) Elem() Type {
595 switch t.Kind() {
596 case Array:
597 tt := (*arrayType)(unsafe.Pointer(t))
598 return toType(tt.elem)
599 case Chan:
600 tt := (*chanType)(unsafe.Pointer(t))
601 return toType(tt.elem)
602 case Map:
603 tt := (*mapType)(unsafe.Pointer(t))
604 return toType(tt.elem)
605 case Ptr:
606 tt := (*ptrType)(unsafe.Pointer(t))
607 return toType(tt.elem)
608 case Slice:
609 tt := (*sliceType)(unsafe.Pointer(t))
610 return toType(tt.elem)
611 }
612 panic("reflect: Elem of invalid type")
613 }
614
615 func (t *rtype) In(i int) Type {
616 if t.Kind() != Func {
617 panic("reflect: In of non-func type")
618 }
619 tt := (*funcType)(unsafe.Pointer(t))
620 return toType(tt.in()[i])
621 }
622
623 func (t *rtype) Key() Type {
624 if t.Kind() != Map {
625 panic("reflect: Key of non-map type")
626 }
627 tt := (*mapType)(unsafe.Pointer(t))
628 return toType(tt.key)
629 }
630
631 func (t *rtype) Len() int {
632 if t.Kind() != Array {
633 panic("reflect: Len of non-array type")
634 }
635 tt := (*arrayType)(unsafe.Pointer(t))
636 return int(tt.len)
637 }
638
639 func (t *rtype) NumField() int {
640 if t.Kind() != Struct {
641 panic("reflect: NumField of non-struct type")
642 }
643 tt := (*structType)(unsafe.Pointer(t))
644 return len(tt.fields)
645 }
646
647 func (t *rtype) NumIn() int {
648 if t.Kind() != Func {
649 panic("reflect: NumIn of non-func type")
650 }
651 tt := (*funcType)(unsafe.Pointer(t))
652 return int(tt.inCount)
653 }
654
655 func (t *rtype) NumOut() int {
656 if t.Kind() != Func {
657 panic("reflect: NumOut of non-func type")
658 }
659 tt := (*funcType)(unsafe.Pointer(t))
660 return len(tt.out())
661 }
662
663 func (t *rtype) Out(i int) Type {
664 if t.Kind() != Func {
665 panic("reflect: Out of non-func type")
666 }
667 tt := (*funcType)(unsafe.Pointer(t))
668 return toType(tt.out()[i])
669 }
670
671 func (t *funcType) in() []*rtype {
672 uadd := unsafe.Sizeof(*t)
673 if t.tflag&tflagUncommon != 0 {
674 uadd += unsafe.Sizeof(uncommonType{})
675 }
676 if t.inCount == 0 {
677 return nil
678 }
679 return (*[1 << 20]*rtype)(add(unsafe.Pointer(t), uadd, "t.inCount > 0"))[:t.inCount:t.inCount]
680 }
681
682 func (t *funcType) out() []*rtype {
683 uadd := unsafe.Sizeof(*t)
684 if t.tflag&tflagUncommon != 0 {
685 uadd += unsafe.Sizeof(uncommonType{})
686 }
687 outCount := t.outCount & (1<<15 - 1)
688 if outCount == 0 {
689 return nil
690 }
691 return (*[1 << 20]*rtype)(add(unsafe.Pointer(t), uadd, "outCount > 0"))[t.inCount : t.inCount+outCount : t.inCount+outCount]
692 }
693
694
695
696
697
698
699
700
701 func add(p unsafe.Pointer, x uintptr, whySafe string) unsafe.Pointer {
702 return unsafe.Pointer(uintptr(p) + x)
703 }
704
705
706 func (t *interfaceType) NumMethod() int { return len(t.methods) }
707
708
709
710 func TypeOf(i any) Type {
711 eface := *(*emptyInterface)(unsafe.Pointer(&i))
712 return toType(eface.typ)
713 }
714
715 func (t *rtype) Implements(u Type) bool {
716 if u == nil {
717 panic("reflect: nil type passed to Type.Implements")
718 }
719 if u.Kind() != Interface {
720 panic("reflect: non-interface type passed to Type.Implements")
721 }
722 return implements(u.(*rtype), t)
723 }
724
725 func (t *rtype) AssignableTo(u Type) bool {
726 if u == nil {
727 panic("reflect: nil type passed to Type.AssignableTo")
728 }
729 uu := u.(*rtype)
730 return directlyAssignable(uu, t) || implements(uu, t)
731 }
732
733 func (t *rtype) Comparable() bool {
734 return t.equal != nil
735 }
736
737
738 func implements(T, V *rtype) bool {
739 if T.Kind() != Interface {
740 return false
741 }
742 t := (*interfaceType)(unsafe.Pointer(T))
743 if len(t.methods) == 0 {
744 return true
745 }
746
747
748
749
750
751
752
753
754
755
756
757
758
759 if V.Kind() == Interface {
760 v := (*interfaceType)(unsafe.Pointer(V))
761 i := 0
762 for j := 0; j < len(v.methods); j++ {
763 tm := &t.methods[i]
764 tmName := t.nameOff(tm.name)
765 vm := &v.methods[j]
766 vmName := V.nameOff(vm.name)
767 if vmName.name() == tmName.name() && V.typeOff(vm.typ) == t.typeOff(tm.typ) {
768 if !tmName.isExported() {
769 tmPkgPath := tmName.pkgPath()
770 if tmPkgPath == "" {
771 tmPkgPath = t.pkgPath.name()
772 }
773 vmPkgPath := vmName.pkgPath()
774 if vmPkgPath == "" {
775 vmPkgPath = v.pkgPath.name()
776 }
777 if tmPkgPath != vmPkgPath {
778 continue
779 }
780 }
781 if i++; i >= len(t.methods) {
782 return true
783 }
784 }
785 }
786 return false
787 }
788
789 v := V.uncommon()
790 if v == nil {
791 return false
792 }
793 i := 0
794 vmethods := v.methods()
795 for j := 0; j < int(v.mcount); j++ {
796 tm := &t.methods[i]
797 tmName := t.nameOff(tm.name)
798 vm := vmethods[j]
799 vmName := V.nameOff(vm.name)
800 if vmName.name() == tmName.name() && V.typeOff(vm.mtyp) == t.typeOff(tm.typ) {
801 if !tmName.isExported() {
802 tmPkgPath := tmName.pkgPath()
803 if tmPkgPath == "" {
804 tmPkgPath = t.pkgPath.name()
805 }
806 vmPkgPath := vmName.pkgPath()
807 if vmPkgPath == "" {
808 vmPkgPath = V.nameOff(v.pkgPath).name()
809 }
810 if tmPkgPath != vmPkgPath {
811 continue
812 }
813 }
814 if i++; i >= len(t.methods) {
815 return true
816 }
817 }
818 }
819 return false
820 }
821
822
823
824
825
826
827 func directlyAssignable(T, V *rtype) bool {
828
829 if T == V {
830 return true
831 }
832
833
834
835 if T.hasName() && V.hasName() || T.Kind() != V.Kind() {
836 return false
837 }
838
839
840 return haveIdenticalUnderlyingType(T, V, true)
841 }
842
843 func haveIdenticalType(T, V Type, cmpTags bool) bool {
844 if cmpTags {
845 return T == V
846 }
847
848 if T.Name() != V.Name() || T.Kind() != V.Kind() {
849 return false
850 }
851
852 return haveIdenticalUnderlyingType(T.common(), V.common(), false)
853 }
854
855 func haveIdenticalUnderlyingType(T, V *rtype, cmpTags bool) bool {
856 if T == V {
857 return true
858 }
859
860 kind := T.Kind()
861 if kind != V.Kind() {
862 return false
863 }
864
865
866
867 if Bool <= kind && kind <= Complex128 || kind == String || kind == UnsafePointer {
868 return true
869 }
870
871
872 switch kind {
873 case Array:
874 return T.Len() == V.Len() && haveIdenticalType(T.Elem(), V.Elem(), cmpTags)
875
876 case Chan:
877
878
879
880 if V.chanDir() == bothDir && haveIdenticalType(T.Elem(), V.Elem(), cmpTags) {
881 return true
882 }
883
884
885 return V.chanDir() == T.chanDir() && haveIdenticalType(T.Elem(), V.Elem(), cmpTags)
886
887 case Func:
888 t := (*funcType)(unsafe.Pointer(T))
889 v := (*funcType)(unsafe.Pointer(V))
890 if t.outCount != v.outCount || t.inCount != v.inCount {
891 return false
892 }
893 for i := 0; i < t.NumIn(); i++ {
894 if !haveIdenticalType(t.In(i), v.In(i), cmpTags) {
895 return false
896 }
897 }
898 for i := 0; i < t.NumOut(); i++ {
899 if !haveIdenticalType(t.Out(i), v.Out(i), cmpTags) {
900 return false
901 }
902 }
903 return true
904
905 case Interface:
906 t := (*interfaceType)(unsafe.Pointer(T))
907 v := (*interfaceType)(unsafe.Pointer(V))
908 if len(t.methods) == 0 && len(v.methods) == 0 {
909 return true
910 }
911
912
913 return false
914
915 case Map:
916 return haveIdenticalType(T.Key(), V.Key(), cmpTags) && haveIdenticalType(T.Elem(), V.Elem(), cmpTags)
917
918 case Ptr, Slice:
919 return haveIdenticalType(T.Elem(), V.Elem(), cmpTags)
920
921 case Struct:
922 t := (*structType)(unsafe.Pointer(T))
923 v := (*structType)(unsafe.Pointer(V))
924 if len(t.fields) != len(v.fields) {
925 return false
926 }
927 if t.pkgPath.name() != v.pkgPath.name() {
928 return false
929 }
930 for i := range t.fields {
931 tf := &t.fields[i]
932 vf := &v.fields[i]
933 if tf.name.name() != vf.name.name() {
934 return false
935 }
936 if !haveIdenticalType(tf.typ, vf.typ, cmpTags) {
937 return false
938 }
939 if cmpTags && tf.name.tag() != vf.name.tag() {
940 return false
941 }
942 if tf.offsetEmbed != vf.offsetEmbed {
943 return false
944 }
945 }
946 return true
947 }
948
949 return false
950 }
951
952 type structTypeUncommon struct {
953 structType
954 u uncommonType
955 }
956
957
958
959
960
961
962 func toType(t *rtype) Type {
963 if t == nil {
964 return nil
965 }
966 return t
967 }
968
969
970 func ifaceIndir(t *rtype) bool {
971 return t.kind&kindDirectIface == 0
972 }
973
View as plain text