github.com/switchupcb/yaegi@v0.10.2/internal/unsafe2/unsafe.go (about)

     1  package unsafe2
     2  
     3  import (
     4  	"reflect"
     5  	"unsafe"
     6  )
     7  
     8  type dummy struct{}
     9  
    10  // DummyType represents a stand-in for a recursive type.
    11  var DummyType = reflect.TypeOf(dummy{})
    12  
    13  // the following type sizes must match their original definition in Go src/reflect/type.go.
    14  
    15  type rtype struct {
    16  	_ uintptr
    17  	_ uintptr
    18  	_ uint32
    19  	_ uint32
    20  	_ uintptr
    21  	_ uintptr
    22  	_ uint32
    23  	_ uint32
    24  }
    25  
    26  type emptyInterface struct {
    27  	typ *rtype
    28  	_   unsafe.Pointer
    29  }
    30  
    31  type structField struct {
    32  	_   uintptr
    33  	typ *rtype
    34  	_   uintptr
    35  }
    36  
    37  type structType struct {
    38  	rtype
    39  	_      uintptr
    40  	fields []structField
    41  }
    42  
    43  // SwapFieldType swaps the type of the struct field with the given type.
    44  //
    45  // The struct type must have been created at runtime. This is very unsafe.
    46  func SwapFieldType(s reflect.Type, idx int, t reflect.Type) {
    47  	if s.Kind() != reflect.Struct || idx >= s.NumField() {
    48  		return
    49  	}
    50  
    51  	rtyp := unpackType(s)
    52  	styp := (*structType)(unsafe.Pointer(rtyp))
    53  	f := styp.fields[idx]
    54  	f.typ = unpackType(t)
    55  	styp.fields[idx] = f
    56  }
    57  
    58  func unpackType(t reflect.Type) *rtype {
    59  	v := reflect.New(t).Elem().Interface()
    60  	return (*emptyInterface)(unsafe.Pointer(&v)).typ
    61  }