github.com/jxskiss/gopkg/v2@v2.14.9-0.20240514120614-899f3e7952b4/unsafe/reflectx/unsafeheader.go (about)

     1  package reflectx
     2  
     3  import (
     4  	"fmt"
     5  	"reflect"
     6  	"unsafe"
     7  
     8  	"github.com/jxskiss/gopkg/v2/internal/unsafeheader"
     9  )
    10  
    11  // StringHeader is the runtime representation of a string.
    12  //
    13  // Unlike reflect.StringHeader, its Data field is sufficient to guarantee the
    14  // data it references will not be garbage collected.
    15  type StringHeader = unsafeheader.StringHeader
    16  
    17  // SliceHeader is the runtime representation of a slice.
    18  //
    19  // Unlike reflect.SliceHeader, its Data field is sufficient to guarantee the
    20  // data it references will not be garbage collected.
    21  type SliceHeader = unsafeheader.SliceHeader
    22  
    23  // EmptyInterface is the header for an interface{} value.
    24  // It's a copy type of runtime.eface.
    25  type EmptyInterface struct {
    26  	RType *RType         // *rtype
    27  	Word  unsafe.Pointer // data pointer
    28  }
    29  
    30  // StringToBytes converts a string to []byte without copying memory.
    31  //
    32  // It uses unsafe tricks, it may panic your program or result
    33  // unpredictable behavior.
    34  func StringToBytes(s string) []byte {
    35  	return unsafeheader.StringToBytes(s)
    36  }
    37  
    38  // BytesToString converts a []byte to string without copying memory.
    39  //
    40  // It uses unsafe tricks, it may panic your program or result
    41  // unpredictable behavior.
    42  func BytesToString(b []byte) string {
    43  	return unsafeheader.BytesToString(b)
    44  }
    45  
    46  // EfaceOf casts the empty interface{} pointer to an EmptyInterface pointer.
    47  func EfaceOf(ep *any) EmptyInterface {
    48  	return *(*EmptyInterface)(unsafe.Pointer(ep))
    49  }
    50  
    51  // UnpackSlice unpacks the given slice interface{} to the underlying
    52  // EmptyInterface and SliceHeader.
    53  // It panics if param slice is not a slice.
    54  func UnpackSlice(slice any) (EmptyInterface, *SliceHeader) {
    55  	eface := EfaceOf(&slice)
    56  	if eface.RType.Kind() != reflect.Slice {
    57  		panic(invalidType("UnpackSlice", "slice", slice))
    58  	}
    59  	header := (*SliceHeader)(eface.Word)
    60  	return eface, header
    61  }
    62  
    63  // SliceLen returns the length of the given slice interface{} value.
    64  // The provided slice must be a slice, else it panics.
    65  func SliceLen(slice any) int {
    66  	_, header := UnpackSlice(slice)
    67  	return header.Len
    68  }
    69  
    70  // SliceCap returns the capacity of the given slice interface{} value.
    71  // The provided slice must be a slice, else it panics.
    72  func SliceCap(slice any) int {
    73  	_, header := UnpackSlice(slice)
    74  	return header.Cap
    75  }
    76  
    77  func invalidType(where string, want string, got any) string {
    78  	const invalidType = "%s: invalid type, want %s, got %T"
    79  	return fmt.Sprintf(invalidType, where, want, got)
    80  }