github.com/wfusion/gofusion@v1.1.14/common/utils/gomonkey/creflect/type.go (about)

     1  // Customized reflect package for gomonkey,copy most code from go/src/reflect/type.go
     2  
     3  package creflect
     4  
     5  import (
     6  	"reflect"
     7  	"unsafe"
     8  )
     9  
    10  // rtype is the common implementation of most values.
    11  // rtype must be kept in sync with ../runtime/type.go:/^type._type.
    12  type rtype struct {
    13  	size       uintptr
    14  	ptrdata    uintptr // number of bytes in the type that can contain pointers
    15  	hash       uint32  // hash of type; avoids computation in hash tables
    16  	tflag      tflag   // extra type information flags
    17  	align      uint8   // alignment of variable with this type
    18  	fieldAlign uint8   // alignment of struct field with this type
    19  	kind       uint8   // enumeration for C
    20  	// function for comparing objects of this type
    21  	// (ptr to object A, ptr to object B) -> ==?
    22  	equal     func(unsafe.Pointer, unsafe.Pointer) bool
    23  	gcdata    *byte   // garbage collection data
    24  	str       nameOff // string form
    25  	ptrToThis typeOff // type for pointer to this type, may be zero
    26  }
    27  
    28  func Create(t reflect.Type) *rtype {
    29  	i := *(*funcValue)(unsafe.Pointer(&t))
    30  	r := (*rtype)(i.p)
    31  	return r
    32  }
    33  
    34  type funcValue struct {
    35  	_ uintptr
    36  	p unsafe.Pointer
    37  }
    38  
    39  func funcPointer(v reflect.Method, ok bool) (unsafe.Pointer, bool) {
    40  	return (*funcValue)(unsafe.Pointer(&v.Func)).p, ok
    41  }
    42  func MethodByName(r reflect.Type, name string) (fn unsafe.Pointer, ok bool) {
    43  	t := Create(r)
    44  	if r.Kind() == reflect.Interface {
    45  		return funcPointer(r.MethodByName(name))
    46  	}
    47  	ut := t.uncommon(r)
    48  	if ut == nil {
    49  		return nil, false
    50  	}
    51  
    52  	for _, p := range ut.methods() {
    53  		if t.nameOff(p.name).name() == name {
    54  			return t.Method(p), true
    55  		}
    56  	}
    57  	return nil, false
    58  }
    59  
    60  func (t *rtype) Method(p method) (fn unsafe.Pointer) {
    61  	tfn := t.textOff(p.tfn)
    62  	fn = unsafe.Pointer(&tfn)
    63  	return
    64  }
    65  
    66  type tflag uint8
    67  type nameOff int32 // offset to a name
    68  type typeOff int32 // offset to an *rtype
    69  type textOff int32 // offset from top of text section
    70  
    71  //go:linkname resolveTextOff reflect.resolveTextOff
    72  func resolveTextOff(rtype unsafe.Pointer, off int32) unsafe.Pointer
    73  
    74  func (t *rtype) textOff(off textOff) unsafe.Pointer {
    75  	return resolveTextOff(unsafe.Pointer(t), int32(off))
    76  }
    77  
    78  //go:linkname resolveNameOff reflect.resolveNameOff
    79  func resolveNameOff(ptrInModule unsafe.Pointer, off int32) unsafe.Pointer
    80  
    81  func (t *rtype) nameOff(off nameOff) name {
    82  	return name{(*byte)(resolveNameOff(unsafe.Pointer(t), int32(off)))}
    83  }
    84  
    85  const (
    86  	tflagUncommon tflag = 1 << 0
    87  )
    88  
    89  // uncommonType is present only for defined types or types with methods
    90  type uncommonType struct {
    91  	pkgPath nameOff // import path; empty for built-in types like int, string
    92  	mcount  uint16  // number of methods
    93  	xcount  uint16  // number of exported methods
    94  	moff    uint32  // offset from this uncommontype to [mcount]method
    95  	_       uint32  // unused
    96  }
    97  
    98  // ptrType represents a pointer type.
    99  type ptrType struct {
   100  	rtype
   101  	elem *rtype // pointer element (pointed at) type
   102  }
   103  
   104  // funcType represents a function type.
   105  type funcType struct {
   106  	rtype
   107  	inCount  uint16
   108  	outCount uint16 // top bit is set if last input parameter is ...
   109  }
   110  
   111  func add(p unsafe.Pointer, x uintptr, whySafe string) unsafe.Pointer {
   112  	return unsafe.Pointer(uintptr(p) + x)
   113  }
   114  
   115  // interfaceType represents an interface type.
   116  type interfaceType struct {
   117  	rtype
   118  	pkgPath name      // import path
   119  	methods []imethod // sorted by hash
   120  }
   121  
   122  type imethod struct {
   123  	name nameOff // name of method
   124  	typ  typeOff // .(*FuncType) underneath
   125  }
   126  
   127  type String struct {
   128  	Data unsafe.Pointer
   129  	Len  int
   130  }
   131  
   132  func (t *rtype) uncommon(r reflect.Type) *uncommonType {
   133  	if t.tflag&tflagUncommon == 0 {
   134  		return nil
   135  	}
   136  	switch r.Kind() {
   137  	case reflect.Ptr:
   138  		type u struct {
   139  			ptrType
   140  			u uncommonType
   141  		}
   142  		return &(*u)(unsafe.Pointer(t)).u
   143  	case reflect.Func:
   144  		type u struct {
   145  			funcType
   146  			u uncommonType
   147  		}
   148  		return &(*u)(unsafe.Pointer(t)).u
   149  	case reflect.Interface:
   150  		type u struct {
   151  			interfaceType
   152  			u uncommonType
   153  		}
   154  		return &(*u)(unsafe.Pointer(t)).u
   155  	case reflect.Struct:
   156  		type u struct {
   157  			interfaceType
   158  			u uncommonType
   159  		}
   160  		return &(*u)(unsafe.Pointer(t)).u
   161  	default:
   162  		return nil
   163  	}
   164  }
   165  
   166  // Method on non-interface type
   167  type method struct {
   168  	name nameOff // name of method
   169  	mtyp typeOff // method type (without receiver)
   170  	ifn  textOff // fn used in interface call (one-word receiver)
   171  	tfn  textOff // fn used for normal method call
   172  }
   173  
   174  func (t *uncommonType) methods() []method {
   175  	if t.mcount == 0 {
   176  		return nil
   177  	}
   178  	return (*[1 << 16]method)(add(unsafe.Pointer(t), uintptr(t.moff), "t.mcount > 0"))[:t.mcount:t.mcount]
   179  }