amuz.es/src/infra/goutils@v0.1.3/runtime/reflect.go (about)

     1  package runtime
     2  
     3  import (
     4  	"unsafe"
     5  	"reflect"
     6  	"fmt"
     7  )
     8  
     9  //go:linkname typesByString reflect.typesByString
    10  //go:nosplit
    11  func typesByString(s string) []unsafe.Pointer
    12  
    13  /*
    14  TypeByString tries to find a reflect.Type corresponding to the type specified by
    15  s.
    16  It calls the unexported `reflect.typesByString` to do so. It will fail if
    17  the type can't be found or if more than one type with the given name exist.
    18  This relies on the following assumptions:
    19      * The signature of `reflect.typesByString` must not change
    20      * The value returned by `reflect.TypeOf(0)` is a `*reflect.rtype`
    21      * The `reflect.Value` struct contains a `ptr` field of type `unsafe.Pointer`
    22  */
    23  func TypeByString(s string) (reflect.Type, error) {
    24  	types := typesByString(s)
    25  
    26  	if len(types) == 0 {
    27  		return nil, fmt.Errorf("Type '%s' not found", s)
    28  	}
    29  	if len(types) > 1 {
    30  		return nil, fmt.Errorf("Type '%s' is ambiguous", s)
    31  	}
    32  
    33  	t := types[0]
    34  
    35  	pRtypeType := reflect.ValueOf(reflect.TypeOf(0)).Type()
    36  	rtype := reflect.New(pRtypeType).Elem()
    37  
    38  	ptr := unsafe.Pointer(reflect.ValueOf(rtype).FieldByName("ptr").Pointer())
    39  	*(*unsafe.Pointer)(ptr) = t
    40  
    41  	typ := rtype.Interface().(reflect.Type)
    42  	return typ, nil
    43  }