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 }