github.com/volts-dev/volts@v0.0.0-20240120094013-5e9c65924106/internal/test/router/reflect.go (about)

     1  package router
     2  
     3  import (
     4  	"reflect"
     5  	"sync"
     6  	"unsafe"
     7  )
     8  
     9  const (
    10  	kindDirectIface = 1 << 5
    11  	//kindGCProg      = 1 << 6 // Type.gc points to GC program
    12  	kindMask = (1 << 5) - 1
    13  	// tflagUncommon means that there is a pointer, *uncommonType,
    14  	// just beyond the outer type structure.
    15  	//
    16  	// For example, if t.Kind() == Struct and t.tflag&tflagUncommon != 0,
    17  	// then t has uncommonType data and it can be accessed as:
    18  	//
    19  	//	type tUncommon struct {
    20  	//		structType
    21  	//		u uncommonType
    22  	//	}
    23  	//	u := &(*tUncommon)(unsafe.Pointer(t)).u
    24  	tflagUncommon tflag = 1 << 0
    25  )
    26  const (
    27  	flagKindWidth        = 5 // there are 27 kinds
    28  	flagKindMask    flag = 1<<flagKindWidth - 1
    29  	flagStickyRO    flag = 1 << 5
    30  	flagEmbedRO     flag = 1 << 6
    31  	flagIndir       flag = 1 << 7
    32  	flagAddr        flag = 1 << 8
    33  	flagMethod      flag = 1 << 9
    34  	flagMethodShift      = 10
    35  	flagRO          flag = flagStickyRO | flagEmbedRO
    36  )
    37  
    38  type flag uintptr
    39  
    40  func (f flag) kind() reflect.Kind {
    41  	return reflect.Kind(f & flagKindMask)
    42  }
    43  
    44  func (f flag) ro() flag {
    45  	if f&flagRO != 0 {
    46  		return flagStickyRO
    47  	}
    48  	return 0
    49  }
    50  
    51  type nameOff int32 // offset to a name
    52  type typeOff int32 // offset to an *rtype
    53  type textOff int32 // offset from top of text section
    54  
    55  // tflag is used by an rtype to signal what extra type information is
    56  // available in the memory directly following the rtype value.
    57  //
    58  // tflag values must be kept in sync with copies in:
    59  //	cmd/compile/internal/reflectdata/reflect.go
    60  //	cmd/link/internal/ld/decodesym.go
    61  //	runtime/type.go
    62  type tflag uint8
    63  
    64  // String is the runtime representation of a string.
    65  // It cannot be used safely or portably and its representation may
    66  // change in a later release.
    67  //
    68  // Unlike reflect.StringHeader, its Data field is sufficient to guarantee the
    69  // data it references will not be garbage collected.
    70  type String struct {
    71  	Data unsafe.Pointer
    72  	Len  int
    73  }
    74  
    75  // name is an encoded type name with optional extra data.
    76  //
    77  // The first byte is a bit field containing:
    78  //
    79  //	1<<0 the name is exported
    80  //	1<<1 tag data follows the name
    81  //	1<<2 pkgPath nameOff follows the name and tag
    82  //
    83  // Following that, there is a varint-encoded length of the name,
    84  // followed by the name itself.
    85  //
    86  // If tag data is present, it also has a varint-encoded length
    87  // followed by the tag itself.
    88  //
    89  // If the import path follows, then 4 bytes at the end of
    90  // the data form a nameOff. The import path is only set for concrete
    91  // methods that are defined in a different package than their type.
    92  //
    93  // If a name starts with "*", then the exported bit represents
    94  // whether the pointed to type is exported.
    95  //
    96  // Note: this encoding must match here and in:
    97  //   cmd/compile/internal/reflectdata/reflect.go
    98  //   runtime/type.go
    99  //   internal/reflectlite/type.go
   100  //   cmd/link/internal/ld/decodesym.go
   101  
   102  type name struct {
   103  	bytes *byte
   104  }
   105  type Value struct {
   106  	typ *rtype
   107  	ptr unsafe.Pointer
   108  	flag
   109  }
   110  
   111  // imethod represents a method on an interface type
   112  type imethod struct {
   113  	name nameOff // name of method
   114  	typ  typeOff // .(*FuncType) underneath
   115  }
   116  
   117  // interfaceType represents an interface type.
   118  type interfaceType struct {
   119  	rtype
   120  	pkgPath name      // import path
   121  	methods []imethod // sorted by hash
   122  }
   123  
   124  func (n name) data(off int, whySafe string) *byte {
   125  	return (*byte)(add(unsafe.Pointer(n.bytes), uintptr(off), whySafe))
   126  }
   127  
   128  // readVarint parses a varint as encoded by encoding/binary.
   129  // It returns the number of encoded bytes and the encoded value.
   130  func (n name) readVarint(off int) (int, int) {
   131  	v := 0
   132  	for i := 0; ; i++ {
   133  		x := *n.data(off+i, "read varint")
   134  		v += int(x&0x7f) << (7 * i)
   135  		if x&0x80 == 0 {
   136  			return i + 1, v
   137  		}
   138  	}
   139  }
   140  func (n name) name() (s string) {
   141  	if n.bytes == nil {
   142  		return
   143  	}
   144  	i, l := n.readVarint(1)
   145  	hdr := (*String)(unsafe.Pointer(&s))
   146  	hdr.Data = unsafe.Pointer(n.data(1+i, "non-empty string"))
   147  	hdr.Len = l
   148  	return
   149  }
   150  
   151  type (
   152  	// rtype is the common implementation of most values.
   153  	// It is embedded in other struct types.
   154  	//
   155  	// rtype must be kept in sync with ../runtime/type.go:/^type._type.
   156  	rtype struct {
   157  		size       uintptr
   158  		ptrdata    uintptr // number of bytes in the type that can contain pointers
   159  		hash       uint32  // hash of type; avoids computation in hash tables
   160  		tflag      tflag   // extra type information flags
   161  		align      uint8   // alignment of variable with this type
   162  		fieldAlign uint8   // alignment of struct field with this type
   163  		kind       uint8   // enumeration for C
   164  		// function for comparing objects of this type
   165  		// (ptr to object A, ptr to object B) -> ==?
   166  		equal     func(unsafe.Pointer, unsafe.Pointer) bool
   167  		gcdata    *byte   // garbage collection data
   168  		str       nameOff // string form
   169  		ptrToThis typeOff // type for pointer to this type, may be zero
   170  	}
   171  
   172  	// uncommonType is present only for defined types or types with methods
   173  	// (if T is a defined type, the uncommonTypes for T and *T have methods).
   174  	// Using a pointer to this struct reduces the overall size required
   175  	// to describe a non-defined type with no methods.
   176  	uncommonType struct {
   177  		pkgPath nameOff // import path; empty for built-in types like int, string
   178  		mcount  uint16  // number of methods
   179  		xcount  uint16  // number of exported methods
   180  		moff    uint32  // offset from this uncommontype to [mcount]method
   181  		_       uint32  // unused
   182  	}
   183  	// Method on non-interface type
   184  	method struct {
   185  		name nameOff // name of method
   186  		mtyp typeOff // method type (without receiver)
   187  		ifn  textOff // fn used in interface call (one-word receiver)
   188  		tfn  textOff // fn used for normal method call
   189  	}
   190  
   191  	// ptrType represents a pointer type.
   192  	ptrType struct {
   193  		rtype
   194  		elem *rtype // pointer element (pointed at) type
   195  	}
   196  )
   197  
   198  // ValueOf returns a new Value initialized to the concrete value
   199  // stored in the interface i. ValueOf(nil) returns the zero Value.
   200  func ValueOf(i interface{}) Value {
   201  	if i == nil {
   202  		return Value{}
   203  	}
   204  
   205  	// TODO: Maybe allow contents of a Value to live on the stack.
   206  	// For now we make the contents always escape to the heap. It
   207  	// makes life easier in a few places (see chanrecv/mapassign
   208  	// comment below).
   209  	//escapes(i)
   210  
   211  	e := (*emptyInterface)(unsafe.Pointer(&i))
   212  	// NOTE: don't read e.word until we know whether it is really a pointer or not.
   213  	t := e.typ
   214  	if t == nil {
   215  		return Value{}
   216  	}
   217  	f := flag(t.Kind())
   218  	if t.kind&kindDirectIface == 0 {
   219  		f |= flagIndir
   220  	}
   221  
   222  	//return *(*reflect.Value)(unsafe.Pointer(&Value{t, e.word, f}))
   223  	return Value{t, e.word, f}
   224  }
   225  
   226  // MethodByName returns a function value corresponding to the method
   227  // of v with the given name.
   228  // The arguments to a Call on the returned function should not include
   229  // a receiver; the returned function will always use v as the receiver.
   230  // It returns the zero Value if no method was found.
   231  func (v Value) MethodByName(name string) Value {
   232  	if v.typ == nil {
   233  		//panic(&ValueError{"reflect.Value.MethodByName", Invalid})
   234  	}
   235  	if v.flag&flagMethod != 0 {
   236  		return Value{}
   237  	}
   238  	m, ok := v.typ.MethodByName(name)
   239  	if !ok {
   240  		return Value{}
   241  	}
   242  	return v.Method(m.Index)
   243  }
   244  
   245  // Interface returns v's current value as an interface{}.
   246  // It is equivalent to:
   247  //	var i interface{} = (v's underlying value)
   248  // It panics if the Value was obtained by accessing
   249  // unexported struct fields.
   250  func (v Value) Interface() (i interface{}) {
   251  	return valueInterface(v, true)
   252  }
   253  
   254  // ifaceIndir reports whether t is stored indirectly in an interface value.
   255  func ifaceIndir(t *rtype) bool {
   256  	return t.kind&kindDirectIface == 0
   257  }
   258  
   259  //go:linkname unsafe_New reflect.unsafe_New
   260  func unsafe_New(rtype unsafe.Pointer) unsafe.Pointer
   261  
   262  //go:linkname typedmemmove reflect.typedmemmove
   263  func typedmemmove(rtype unsafe.Pointer, dst, src unsafe.Pointer)
   264  
   265  //go:linkname unsafe_NewArray reflect.unsafe_NewArray
   266  func unsafe_NewArray(rtype unsafe.Pointer, length int) unsafe.Pointer
   267  
   268  // packEface converts v to the empty interface.
   269  func packEface(v Value) any {
   270  	t := v.typ
   271  	var i any
   272  	e := (*emptyInterface)(unsafe.Pointer(&i))
   273  	// First, fill in the data portion of the interface.
   274  	switch {
   275  	case ifaceIndir(t):
   276  		if v.flag&flagIndir == 0 {
   277  			panic("bad indir")
   278  		}
   279  		// Value is indirect, and so is the interface we're making.
   280  		ptr := v.ptr
   281  		if v.flag&flagAddr != 0 {
   282  			// TODO: pass safe boolean from valueInterface so
   283  			// we don't need to copy if safe==true?
   284  			c := unsafe_New((unsafe.Pointer)(t))
   285  			typedmemmove((unsafe.Pointer)(t), c, ptr)
   286  			ptr = c
   287  		}
   288  		e.word = ptr
   289  	case v.flag&flagIndir != 0:
   290  		// Value is indirect, but interface is direct. We need
   291  		// to load the data at v.ptr into the interface data word.
   292  		e.word = *(*unsafe.Pointer)(v.ptr)
   293  	default:
   294  		// Value is direct, and so is the interface.
   295  		e.word = v.ptr
   296  	}
   297  	// Now, fill in the type portion. We're very careful here not
   298  	// to have any operation between the e.word and e.typ assignments
   299  	// that would let the garbage collector observe the partially-built
   300  	// interface value.
   301  	e.typ = t
   302  	return i
   303  }
   304  
   305  func valueInterface(v Value, safe bool) any {
   306  	if v.flag == 0 {
   307  		//panic(&ValueError{"reflect.Value.Interface", Invalid})
   308  	}
   309  	if safe && v.flag&flagRO != 0 {
   310  		// Do not allow access to unexported values via Interface,
   311  		// because they might be pointers that should not be
   312  		// writable or methods or function that should not be callable.
   313  		panic("reflect.Value.Interface: cannot return value obtained from unexported field or method")
   314  	}
   315  	//// 本身就是个 method
   316  	if v.flag&flagMethod != 0 {
   317  		//v = makeMethodValue("Interface", v)
   318  	}
   319  	/*
   320  		if v.kind() == reflect.Interface {
   321  			// Special case: return the element inside the interface.
   322  			// Empty interface has one layout, all interfaces with
   323  			// methods have a second layout.
   324  			if v.NumMethod() == 0 {
   325  				return *(*any)(v.ptr)
   326  			}
   327  			return *(*interface {
   328  				M()
   329  			})(v.ptr)
   330  		}
   331  	*/
   332  	// TODO: pass safe to packEface so we don't need to copy if safe==true?
   333  	return packEface(v)
   334  }
   335  
   336  // Method returns a function value corresponding to v's i'th method.
   337  // The arguments to a Call on the returned function should not include
   338  // a receiver; the returned function will always use v as the receiver.
   339  // Method panics if i is out of range or if v is a nil interface value.
   340  func (v Value) Method(i int) Value {
   341  	if v.typ == nil {
   342  		//panic(&ValueError{"reflect.Value.Method", Invalid})
   343  	}
   344  	if v.flag&flagMethod != 0 || uint(i) >= uint(v.typ.NumMethod()) {
   345  		panic("reflect: Method index out of range")
   346  	}
   347  	if v.typ.Kind() == reflect.Interface && v.IsNil() {
   348  		panic("reflect: Method on nil interface value")
   349  	}
   350  	fl := v.flag.ro() | (v.flag & flagIndir)
   351  	fl |= flag(reflect.Func)
   352  	fl |= flag(i)<<flagMethodShift | flagMethod
   353  	return Value{v.typ, v.ptr, fl}
   354  }
   355  
   356  // IsNil reports whether its argument v is nil. The argument must be
   357  // a chan, func, interface, map, pointer, or slice value; if it is
   358  // not, IsNil panics. Note that IsNil is not always equivalent to a
   359  // regular comparison with nil in Go. For example, if v was created
   360  // by calling ValueOf with an uninitialized interface variable i,
   361  // i==nil will be true but v.IsNil will panic as v will be the zero
   362  // Value.
   363  func (v Value) IsNil() bool {
   364  	k := v.kind()
   365  	switch k {
   366  	case reflect.Chan, reflect.Func, reflect.Map, reflect.Pointer, reflect.UnsafePointer:
   367  		if v.flag&flagMethod != 0 {
   368  			return false
   369  		}
   370  		ptr := v.ptr
   371  		if v.flag&flagIndir != 0 {
   372  			ptr = *(*unsafe.Pointer)(ptr)
   373  		}
   374  		return ptr == nil
   375  	case reflect.Interface, reflect.Slice:
   376  		// Both interface and slice are nil if first word is 0.
   377  		// Both are always bigger than a word; assume flagIndir.
   378  		return *(*unsafe.Pointer)(v.ptr) == nil
   379  	}
   380  	panic(&reflect.ValueError{Method: "reflect.Value.IsNil", Kind: v.kind()})
   381  }
   382  func (t *rtype) Kind() reflect.Kind { return reflect.Kind(t.kind & kindMask) }
   383  
   384  //go:linkname resolveTypeOff reflect.resolveTypeOff
   385  func resolveTypeOff(rtype unsafe.Pointer, off int32) unsafe.Pointer
   386  
   387  // ptrMap is the cache for PointerTo.
   388  var ptrMap sync.Map // map[*rtype]*ptrType
   389  func (t *rtype) typeOff(off typeOff) *rtype {
   390  	return (*rtype)(resolveTypeOff(unsafe.Pointer(t), int32(off)))
   391  }
   392  func (t *rtype) uncommon() *uncommonType {
   393  	if t.tflag&tflagUncommon == 0 {
   394  		return nil
   395  	}
   396  	switch t.Kind() {
   397  	case reflect.Struct:
   398  		//return &(*structTypeUncommon)(unsafe.Pointer(t)).u
   399  		return nil
   400  	case reflect.Pointer:
   401  		type u struct {
   402  			ptrType
   403  			u uncommonType
   404  		}
   405  		return &(*u)(unsafe.Pointer(t)).u
   406  
   407  	case reflect.Func:
   408  		return nil
   409  		/*		type u struct {
   410  						funcType
   411  						u uncommonType
   412  					}
   413  					return &(*u)(unsafe.Pointer(t)).u
   414  				case Slice:
   415  					type u struct {
   416  						sliceType
   417  						u uncommonType
   418  					}
   419  					return &(*u)(unsafe.Pointer(t)).u
   420  				case Array:
   421  					type u struct {
   422  						arrayType
   423  						u uncommonType
   424  					}
   425  					return &(*u)(unsafe.Pointer(t)).u
   426  				case Chan:
   427  					type u struct {
   428  						chanType
   429  						u uncommonType
   430  					}
   431  					return &(*u)(unsafe.Pointer(t)).u
   432  				case Map:
   433  					type u struct {
   434  						mapType
   435  						u uncommonType
   436  					}
   437  					return &(*u)(unsafe.Pointer(t)).u
   438  				case Interface:
   439  					type u struct {
   440  						interfaceType
   441  						u uncommonType
   442  					}
   443  					return &(*u)(unsafe.Pointer(t)).u
   444  		*/
   445  	default:
   446  		type u struct {
   447  			rtype
   448  			u uncommonType
   449  		}
   450  		return &(*u)(unsafe.Pointer(t)).u
   451  	}
   452  }
   453  
   454  func resolveNameOff(ptrInModule unsafe.Pointer, off nameOff) name {
   455  	if off == 0 {
   456  		return name{}
   457  	}
   458  	base := uintptr(ptrInModule)
   459  	for md := &Firstmoduledata; md != nil; md = md.next {
   460  		if base >= md.types && base < md.etypes {
   461  			res := md.types + uintptr(off)
   462  			if res > md.etypes {
   463  				//println("runtime: nameOff", hex(off), "out of range", hex(md.types), "-", hex(md.etypes))
   464  				//throw("runtime: name offset out of range")
   465  			}
   466  			return name{(*byte)(unsafe.Pointer(res))}
   467  		}
   468  	}
   469  	return name{}
   470  	// No module found. see if it is a run time name.
   471  	/*
   472  		reflectOffsLock()
   473  		res, found := reflectOffs.m[int32(off)]
   474  		reflectOffsUnlock()
   475  		if !found {
   476  			println("runtime: nameOff", hex(off), "base", hex(base), "not in ranges:")
   477  			for next := &firstmoduledata; next != nil; next = next.next {
   478  				println("\ttypes", hex(next.types), "etypes", hex(next.etypes))
   479  			}
   480  			throw("runtime: name offset base pointer out of range")
   481  		}
   482  
   483  		return name{(*byte)(res)}
   484  	*/
   485  }
   486  
   487  func reflect_resolveNameOff(ptrInModule unsafe.Pointer, off int32) unsafe.Pointer {
   488  	return unsafe.Pointer(resolveNameOff(ptrInModule, nameOff(off)).bytes)
   489  }
   490  
   491  func (t *rtype) nameOff(off nameOff) name {
   492  	return name{(*byte)(reflect_resolveNameOff(unsafe.Pointer(t), int32(off)))}
   493  }
   494  
   495  func (t *rtype) exportedMethods() []method {
   496  	ut := t.uncommon()
   497  	if ut == nil {
   498  		return nil
   499  	}
   500  	return ut.exportedMethods()
   501  }
   502  
   503  func (t *rtype) NumMethod() int {
   504  	if t.Kind() == reflect.Interface {
   505  		tt := (*interfaceType)(unsafe.Pointer(t))
   506  		return tt.NumMethod()
   507  	}
   508  	return len(t.exportedMethods())
   509  }
   510  
   511  func (t *rtype) SetMethodByName(name, newName string) {
   512  	if t.Kind() == reflect.Interface {
   513  		//tt := (*interfaceType)(unsafe.Pointer(t))
   514  		//return tt.MethodByName(name)
   515  	}
   516  	ut := t.uncommon()
   517  
   518  	// TODO(mdempsky): Binary search.
   519  	for _, p := range ut.exportedMethods() {
   520  		if t.nameOff(p.name).name() == name {
   521  			//return t.Method(i), true
   522  			//str:=[]byte{'a','d'}
   523  			//t.nameOff(p.name).bytes =  (*byte)(unsafe.Pointer(&str))
   524  		}
   525  	}
   526  
   527  }
   528  
   529  func (t *rtype) MethodByName(name string) (m reflect.Method, ok bool) {
   530  	if t.Kind() == reflect.Interface {
   531  		//tt := (*interfaceType)(unsafe.Pointer(t))
   532  		//return tt.MethodByName(name)
   533  	}
   534  	ut := t.uncommon()
   535  	if ut == nil {
   536  		return reflect.Method{}, false
   537  	}
   538  	// TODO(mdempsky): Binary search.
   539  	for _, p := range ut.exportedMethods() {
   540  		if t.nameOff(p.name).name() == name {
   541  			//return t.Method(i), true
   542  		}
   543  	}
   544  	return reflect.Method{}, false
   545  }
   546  
   547  // add returns p+x.
   548  //
   549  // The whySafe string is ignored, so that the function still inlines
   550  // as efficiently as p+x, but all call sites should use the string to
   551  // record why the addition is safe, which is to say why the addition
   552  // does not cause x to advance to the very end of p's allocation
   553  // and therefore point incorrectly at the next block in memory.
   554  func add(p unsafe.Pointer, x uintptr, whySafe string) unsafe.Pointer {
   555  	return unsafe.Pointer(uintptr(p) + x)
   556  }
   557  
   558  func (t *uncommonType) methods() []method {
   559  	if t.mcount == 0 {
   560  		return nil
   561  	}
   562  	return (*[1 << 16]method)(add(unsafe.Pointer(t), uintptr(t.moff), "t.mcount > 0"))[:t.mcount:t.mcount]
   563  }
   564  
   565  func (t *uncommonType) exportedMethods() []method {
   566  	if t.xcount == 0 {
   567  		return nil
   568  	}
   569  	return (*[1 << 16]method)(add(unsafe.Pointer(t), uintptr(t.moff), "t.xcount > 0"))[:t.xcount:t.xcount]
   570  }