github.com/HaHadaxigua/yaegi@v1.0.1/stdlib/unsafe/unsafe.go (about)

     1  //go:build go1.16
     2  // +build go1.16
     3  
     4  // Package unsafe provides wrapper of standard library unsafe package to be imported natively in Yaegi.
     5  package unsafe
     6  
     7  import (
     8  	"reflect"
     9  	"unsafe"
    10  )
    11  
    12  // Symbols stores the map of unsafe package symbols.
    13  var Symbols = map[string]map[string]reflect.Value{}
    14  
    15  func init() {
    16  	Symbols["github.com/traefik/yaegi/stdlib/unsafe/unsafe"] = map[string]reflect.Value{
    17  		"Symbols": reflect.ValueOf(Symbols),
    18  	}
    19  	Symbols["github.com/traefik/yaegi/yaegi"] = map[string]reflect.Value{
    20  		"convert": reflect.ValueOf(convert),
    21  	}
    22  
    23  	// Add builtin functions to unsafe.
    24  	Symbols["unsafe/unsafe"]["Sizeof"] = reflect.ValueOf(sizeof)
    25  	Symbols["unsafe/unsafe"]["Alignof"] = reflect.ValueOf(alignof)
    26  	Symbols["unsafe/unsafe"]["Offsetof"] = reflect.ValueOf("Offsetof") // This symbol is handled directly in interpreter.
    27  }
    28  
    29  func convert(from, to reflect.Type) func(src, dest reflect.Value) {
    30  	switch {
    31  	case to.Kind() == reflect.UnsafePointer && from.Kind() == reflect.Uintptr:
    32  		return uintptrToUnsafePtr
    33  	case to.Kind() == reflect.UnsafePointer:
    34  		return func(src, dest reflect.Value) {
    35  			dest.SetPointer(unsafe.Pointer(src.Pointer()))
    36  		}
    37  	case to.Kind() == reflect.Uintptr && from.Kind() == reflect.UnsafePointer:
    38  		return func(src, dest reflect.Value) {
    39  			ptr := src.Interface().(unsafe.Pointer)
    40  			dest.Set(reflect.ValueOf(uintptr(ptr)))
    41  		}
    42  	case from.Kind() == reflect.UnsafePointer:
    43  		return func(src, dest reflect.Value) {
    44  			ptr := src.Interface().(unsafe.Pointer)
    45  			v := reflect.NewAt(dest.Type().Elem(), ptr)
    46  			dest.Set(v)
    47  		}
    48  	default:
    49  		return nil
    50  	}
    51  }
    52  
    53  func sizeof(i interface{}) uintptr {
    54  	return reflect.ValueOf(i).Type().Size()
    55  }
    56  
    57  func alignof(i interface{}) uintptr {
    58  	return uintptr(reflect.ValueOf(i).Type().Align())
    59  }
    60  
    61  //go:nocheckptr
    62  func uintptrToUnsafePtr(src, dest reflect.Value) {
    63  	dest.SetPointer(unsafe.Pointer(src.Interface().(uintptr))) //nolint:govet
    64  }
    65  
    66  //go:generate ../../internal/cmd/extract/extract unsafe