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

     1  //go:build go1.17
     2  // +build go1.17
     3  
     4  // Package unsafe provides wrapper of standard library unsafe package to be imported natively in Yaegi.
     5  package unsafe
     6  
     7  import (
     8  	"errors"
     9  	"reflect"
    10  	"unsafe"
    11  )
    12  
    13  func init() {
    14  	// Add builtin functions to unsafe.
    15  	Symbols["unsafe/unsafe"]["Add"] = reflect.ValueOf(add)
    16  	Symbols["unsafe/unsafe"]["Slice"] = reflect.ValueOf(slice)
    17  }
    18  
    19  func add(ptr unsafe.Pointer, l int) unsafe.Pointer {
    20  	return unsafe.Pointer(uintptr(ptr) + uintptr(l))
    21  }
    22  
    23  type emptyInterface struct {
    24  	_    uintptr
    25  	data unsafe.Pointer
    26  }
    27  
    28  func slice(i interface{}, l int) interface{} {
    29  	if l == 0 {
    30  		return nil
    31  	}
    32  
    33  	v := reflect.ValueOf(i)
    34  	if v.Kind() != reflect.Ptr {
    35  		panic(errors.New("first argument to unsafe.Slice must be pointer"))
    36  	}
    37  	if v.IsNil() {
    38  		panic(errors.New("unsafe.Slice: ptr is nil and len is not zero"))
    39  	}
    40  
    41  	if l < 0 {
    42  		panic(errors.New("unsafe.Slice: len out of range"))
    43  	}
    44  
    45  	ih := *(*emptyInterface)(unsafe.Pointer(&i))
    46  
    47  	inter := reflect.MakeSlice(reflect.SliceOf(v.Type().Elem()), l, l).Interface()
    48  	ptr := (*emptyInterface)(unsafe.Pointer(&inter)).data
    49  	sh := (*reflect.SliceHeader)(ptr)
    50  	sh.Data = uintptr(ih.data)
    51  	sh.Len = l
    52  	sh.Cap = l
    53  
    54  	return inter
    55  }