github.com/prebid/prebid-server/v2@v2.18.0/util/reflectutil/slice.go (about)

     1  package reflectutil
     2  
     3  import (
     4  	"unsafe"
     5  
     6  	"github.com/modern-go/reflect2"
     7  )
     8  
     9  // UnsafeSliceClone clones an existing slice using unsafe.Pointer conventions. Intended
    10  // for use by json iterator extensions and should likely be used no where else. Nil
    11  // behavior is undefined as checks are expected upstream.
    12  func UnsafeSliceClone(ptr unsafe.Pointer, sliceType reflect2.SliceType) unsafe.Pointer {
    13  	// it's also possible to use `sliceType.Elem().RType`, but that returns a `uintptr`
    14  	// which causes `go vet` to emit a warning even though the usage is safe. this approach
    15  	// of copying some internals from the reflect2 package avoids the cast of `uintptr` to
    16  	// `unsafe.Pointer` which keeps `go vet` output clean.
    17  	elemRType := unpackEFace(sliceType.Elem().Type1()).data
    18  
    19  	header := (*sliceHeader)(ptr)
    20  	newHeader := (*sliceHeader)(sliceType.UnsafeMakeSlice(header.Len, header.Cap))
    21  	typedslicecopy(elemRType, *newHeader, *header)
    22  	return unsafe.Pointer(newHeader)
    23  }
    24  
    25  // sliceHeader is copied from the reflect2 package v1.0.2.
    26  type sliceHeader struct {
    27  	Data unsafe.Pointer
    28  	Len  int
    29  	Cap  int
    30  }
    31  
    32  // typedslicecopyis copied from the reflect2 package v1.0.2.
    33  // it copies a slice of elemType values from src to dst,
    34  // returning the number of elements copied.
    35  //
    36  //go:linkname typedslicecopy reflect.typedslicecopy
    37  //go:noescape
    38  func typedslicecopy(elemType unsafe.Pointer, dst, src sliceHeader) int
    39  
    40  // eface is copied from the reflect2 package v1.0.2.
    41  type eface struct {
    42  	rtype unsafe.Pointer
    43  	data  unsafe.Pointer
    44  }
    45  
    46  // unpackEFace is copied from the reflect2 package v1.0.2.
    47  func unpackEFace(obj interface{}) *eface {
    48  	return (*eface)(unsafe.Pointer(&obj))
    49  }