github.com/jxskiss/gopkg@v0.17.3/internal/unsafe.go (about)

     1  package internal
     2  
     3  import (
     4  	"github.com/jxskiss/gopkg/internal/linkname"
     5  	"github.com/jxskiss/gopkg/internal/unsafeheader"
     6  	"reflect"
     7  	"unsafe"
     8  )
     9  
    10  // EmptyInterface is the header for an interface{} value.
    11  // It's a copy type of runtime.eface.
    12  type EmptyInterface struct {
    13  	RType unsafe.Pointer // *rtype
    14  	Word  unsafe.Pointer
    15  }
    16  
    17  // EFaceOf casts the empty interface{} pointer to an EmptyInterface pointer.
    18  func EFaceOf(ep *interface{}) *EmptyInterface {
    19  	return (*EmptyInterface)(unsafe.Pointer(ep))
    20  }
    21  
    22  // UnpackSlice unpacks the given slice interface{} to unsafeheader.Slice.
    23  func UnpackSlice(slice interface{}) unsafeheader.Slice {
    24  	return *(*unsafeheader.Slice)(EFaceOf(&slice).Word)
    25  }
    26  
    27  // CastInt returns an integer v's value as int64.
    28  // v must be an integer, else it panics.
    29  func CastInt(v interface{}) int64 {
    30  	eface := EFaceOf(&v)
    31  	kind := linkname.Reflect_rtype_Kind(eface.RType)
    32  	return i64table[kind].Cast(eface.Word)
    33  }
    34  
    35  // CastIntPointer returns ptr's value as int64, the underlying value
    36  // is cast to int64 using unsafe tricks according kind.
    37  //
    38  // If ptr is not pointed to an integer or kind does not match ptr,
    39  // the behavior is undefined, it may panic or return incorrect value.
    40  func CastIntPointer(kind reflect.Kind, ptr unsafe.Pointer) int64 {
    41  	return i64table[kind].Cast(ptr)
    42  }
    43  
    44  const (
    45  	ptrBitSize  = 32 << (^uint(0) >> 63)
    46  	ptrByteSize = ptrBitSize / 8
    47  )
    48  
    49  type intInfo struct {
    50  	Size uintptr
    51  	Cast func(unsafe.Pointer) int64
    52  }
    53  
    54  var i64table = [...]intInfo{
    55  	reflect.Int8:    {1, func(p unsafe.Pointer) int64 { return int64(*(*int8)(p)) }},
    56  	reflect.Uint8:   {1, func(p unsafe.Pointer) int64 { return int64(*(*uint8)(p)) }},
    57  	reflect.Int16:   {2, func(p unsafe.Pointer) int64 { return int64(*(*int16)(p)) }},
    58  	reflect.Uint16:  {2, func(p unsafe.Pointer) int64 { return int64(*(*uint16)(p)) }},
    59  	reflect.Int32:   {4, func(p unsafe.Pointer) int64 { return int64(*(*int32)(p)) }},
    60  	reflect.Uint32:  {4, func(p unsafe.Pointer) int64 { return int64(*(*uint32)(p)) }},
    61  	reflect.Int64:   {8, func(p unsafe.Pointer) int64 { return int64(*(*int64)(p)) }},
    62  	reflect.Uint64:  {8, func(p unsafe.Pointer) int64 { return int64(*(*uint64)(p)) }},
    63  	reflect.Int:     {ptrByteSize, func(p unsafe.Pointer) int64 { return int64(*(*int)(p)) }},
    64  	reflect.Uint:    {ptrByteSize, func(p unsafe.Pointer) int64 { return int64(*(*uint)(p)) }},
    65  	reflect.Uintptr: {ptrByteSize, func(p unsafe.Pointer) int64 { return int64(*(*uintptr)(p)) }},
    66  }