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