github.com/traefik/yaegi@v0.15.1/internal/unsafe2/unsafe.go (about)

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