github.com/goplusjs/reflectx@v0.5.4/type.go (about)

     1  // Copyright 2009 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // Package reflect implements run-time reflection, allowing a program to
     6  // manipulate objects with arbitrary types. The typical use is to take a value
     7  // with static type interface{} and extract its dynamic type information by
     8  // calling TypeOf, which returns a Type.
     9  //
    10  // A call to ValueOf returns a Value representing the run-time data.
    11  // Zero takes a Type and returns a Value representing a zero value
    12  // for that type.
    13  //
    14  // See "The Laws of Reflection" for an introduction to reflection in Go:
    15  // https://golang.org/doc/articles/laws_of_reflection.html
    16  
    17  package reflectx
    18  
    19  import (
    20  	"reflect"
    21  	"unsafe"
    22  )
    23  
    24  // memmove copies size bytes to dst from src. No write barriers are used.
    25  //go:noescape
    26  //go:linkname memmove reflect.memmove
    27  func memmove(dst, src unsafe.Pointer, size uintptr)
    28  
    29  // typedmemmove copies a value of type t to dst from src.
    30  //go:noescape
    31  //go:linkname typedmemmove reflect.typedmemmove
    32  func typedmemmove(t *rtype, dst, src unsafe.Pointer)
    33  
    34  // resolveNameOff resolves a name offset from a base pointer.
    35  // The (*rtype).nameOff method is a convenience wrapper for this function.
    36  // Implemented in the runtime package.
    37  //go:linkname resolveNameOff reflect.resolveNameOff
    38  func resolveNameOff(ptrInModule unsafe.Pointer, off int32) unsafe.Pointer
    39  
    40  // resolveTypeOff resolves an *rtype offset from a base type.
    41  // The (*rtype).typeOff method is a convenience wrapper for this function.
    42  // Implemented in the runtime package.
    43  //go:linkname resolveTypeOff reflect.resolveTypeOff
    44  func resolveTypeOff(rtype unsafe.Pointer, off int32) unsafe.Pointer
    45  
    46  // resolveTextOff resolves a function pointer offset from a base type.
    47  // The (*rtype).textOff method is a convenience wrapper for this function.
    48  // Implemented in the runtime package.
    49  //go:linkname resolveTextOff reflect.resolveTextOff
    50  func resolveTextOff(rtype unsafe.Pointer, off int32) unsafe.Pointer
    51  
    52  // addReflectOff adds a pointer to the reflection lookup map in the runtime.
    53  // It returns a new ID that can be used as a typeOff or textOff, and will
    54  // be resolved correctly. Implemented in the runtime package.
    55  //go:linkname addReflectOff reflect.addReflectOff
    56  func addReflectOff(ptr unsafe.Pointer) int32
    57  
    58  //go:linkname newName reflect.newName
    59  func newName(n, tag string, exported bool) name
    60  
    61  // resolveReflectName adds a name to the reflection lookup map in the runtime.
    62  // It returns a new nameOff that can be used to refer to the pointer.
    63  //go:linkname resolveReflectName reflect.resolveReflectName
    64  func resolveReflectName(n name) nameOff
    65  
    66  //go:linkname toType reflect.toType
    67  func toType(t *rtype) reflect.Type
    68  
    69  //go:linkname _nameOff reflect.(*rtype).nameOff
    70  func _nameOff(t *rtype, off nameOff) name
    71  
    72  //go:linkname _typeOff reflect.(*rtype).typeOff
    73  func _typeOff(t *rtype, off typeOff) *rtype
    74  
    75  //go:linkname _textOff reflect.(*rtype).textOff
    76  func _textOff(t *rtype, off textOff) unsafe.Pointer
    77  
    78  func (t *rtype) nameOff(off nameOff) name {
    79  	return _nameOff(t, off)
    80  }
    81  
    82  func (t *rtype) typeOff(off typeOff) *rtype {
    83  	return _typeOff(t, off)
    84  	//return (*rtype)(resolveTypeOff(unsafe.Pointer(t), int32(off)))
    85  }
    86  
    87  func (t *rtype) textOff(off textOff) unsafe.Pointer {
    88  	return _textOff(t, off)
    89  	//return resolveTextOff(unsafe.Pointer(t), int32(off))
    90  }
    91  
    92  // resolveReflectType adds a *rtype to the reflection lookup map in the runtime.
    93  // It returns a new typeOff that can be used to refer to the pointer.
    94  func resolveReflectType(t *rtype) typeOff {
    95  	return typeOff(addReflectOff(unsafe.Pointer(t)))
    96  }
    97  
    98  // resolveReflectText adds a function pointer to the reflection lookup map in
    99  // the runtime. It returns a new textOff that can be used to refer to the
   100  // pointer.
   101  func resolveReflectText(ptr unsafe.Pointer) textOff {
   102  	return textOff(addReflectOff(ptr))
   103  }
   104  
   105  type nameOff int32
   106  type typeOff int32
   107  type textOff int32
   108  
   109  // Method on non-interface type
   110  type method struct {
   111  	name nameOff // name of method
   112  	mtyp typeOff // method type (without receiver)
   113  	ifn  textOff // fn used in interface call (one-word receiver)
   114  	tfn  textOff // fn used for normal method call
   115  }
   116  
   117  type structTypeUncommon struct {
   118  	structType
   119  	u uncommonType
   120  }
   121  
   122  type tflag uint8
   123  
   124  const (
   125  	// tflagUncommon means that there is a pointer, *uncommonType,
   126  	// just beyond the outer type structure.
   127  	//
   128  	// For example, if t.Kind() == Struct and t.tflag&tflagUncommon != 0,
   129  	// then t has uncommonType data and it can be accessed as:
   130  	//
   131  	//	type tUncommon struct {
   132  	//		structType
   133  	//		u uncommonType
   134  	//	}
   135  	//	u := &(*tUncommon)(unsafe.Pointer(t)).u
   136  	tflagUncommon tflag = 1 << 0
   137  
   138  	// tflagExtraStar means the name in the str field has an
   139  	// extraneous '*' prefix. This is because for most types T in
   140  	// a program, the type *T also exists and reusing the str data
   141  	// saves binary size.
   142  	tflagExtraStar tflag = 1 << 1
   143  
   144  	// tflagNamed means the type has a name.
   145  	tflagNamed tflag = 1 << 2
   146  
   147  	// tflagRegularMemory means that equal and hash functions can treat
   148  	// this type as a single region of t.size bytes.
   149  	tflagRegularMemory tflag = 1 << 3
   150  )
   151  
   152  type rtype struct {
   153  	size       uintptr
   154  	ptrdata    uintptr // number of bytes in the type that can contain pointers
   155  	hash       uint32  // hash of type; avoids computation in hash tables
   156  	tflag      tflag   // extra type information flags
   157  	align      uint8   // alignment of variable with this type
   158  	fieldAlign uint8   // alignment of struct field with this type
   159  	kind       uint8   // enumeration for C
   160  	// function for comparing objects of this type
   161  	// (ptr to object A, ptr to object B) -> ==?
   162  	equal     func(unsafe.Pointer, unsafe.Pointer) bool
   163  	gcdata    *byte   // garbage collection data
   164  	str       nameOff // string form
   165  	ptrToThis typeOff // type for pointer to this type, may be zero
   166  }
   167  
   168  const (
   169  	kindDirectIface = 1 << 5
   170  	kindGCProg      = 1 << 6 // Type.gc points to GC program
   171  	kindMask        = (1 << 5) - 1
   172  )
   173  
   174  func (t *rtype) Kind() reflect.Kind {
   175  	return reflect.Kind(t.kind & kindMask)
   176  }
   177  
   178  // add returns p+x.
   179  //
   180  // The whySafe string is ignored, so that the function still inlines
   181  // as efficiently as p+x, but all call sites should use the string to
   182  // record why the addition is safe, which is to say why the addition
   183  // does not cause x to advance to the very end of p's allocation
   184  // and therefore point incorrectly at the next block in memory.
   185  func add(p unsafe.Pointer, x uintptr, whySafe string) unsafe.Pointer {
   186  	return unsafe.Pointer(uintptr(p) + x)
   187  }
   188  
   189  // stringHeader is a safe version of StringHeader used within this package.
   190  type stringHeader struct {
   191  	Data unsafe.Pointer
   192  	Len  int
   193  }
   194  
   195  // ChanDir represents a channel type's direction.
   196  type ChanDir int
   197  
   198  const (
   199  	RecvDir ChanDir             = 1 << iota // <-chan
   200  	SendDir                                 // chan<-
   201  	BothDir = RecvDir | SendDir             // chan
   202  )
   203  
   204  // arrayType represents a fixed array type.
   205  type arrayType struct {
   206  	rtype
   207  	elem  *rtype // array element type
   208  	slice *rtype // slice type
   209  	len   uintptr
   210  }
   211  
   212  // chanType represents a channel type.
   213  type chanType struct {
   214  	rtype
   215  	elem *rtype  // channel element type
   216  	dir  uintptr // channel direction (ChanDir)
   217  }
   218  
   219  // imethod represents a method on an interface type
   220  type imethod struct {
   221  	name nameOff // name of method
   222  	typ  typeOff // .(*FuncType) underneath
   223  }
   224  
   225  // interfaceType represents an interface type.
   226  type interfaceType struct {
   227  	rtype
   228  	pkgPath name      // import path
   229  	methods []imethod // sorted by hash
   230  }
   231  
   232  // mapType represents a map type.
   233  type mapType struct {
   234  	rtype
   235  	key    *rtype // map key type
   236  	elem   *rtype // map element (value) type
   237  	bucket *rtype // internal bucket structure
   238  	// function for hashing keys (ptr to key, seed) -> hash
   239  	hasher     func(unsafe.Pointer, uintptr) uintptr
   240  	keysize    uint8  // size of key slot
   241  	valuesize  uint8  // size of value slot
   242  	bucketsize uint16 // size of bucket
   243  	flags      uint32
   244  }
   245  
   246  // ptrType represents a pointer type.
   247  type ptrType struct {
   248  	rtype
   249  	elem *rtype // pointer element (pointed at) type
   250  }
   251  
   252  // sliceType represents a slice type.
   253  type sliceType struct {
   254  	rtype
   255  	elem *rtype // slice element type
   256  }
   257  
   258  // struct field
   259  type structField struct {
   260  	name        name    // name is always non-empty
   261  	typ         *rtype  // type of field
   262  	offsetEmbed uintptr // byte offset of field<<1 | isEmbedded
   263  }
   264  
   265  func (f *structField) offset() uintptr {
   266  	return f.offsetEmbed >> 1
   267  }
   268  
   269  func (f *structField) embedded() bool {
   270  	return f.offsetEmbed&1 != 0
   271  }
   272  
   273  // structType represents a struct type.
   274  type structType struct {
   275  	rtype
   276  	pkgPath name
   277  	fields  []structField // sorted by offset
   278  }