gitee.com/sy_183/go-common@v1.0.5-0.20231205030221-958cfe129b47/slice/unsafe/unsafe.go (about)

     1  package unsafe
     2  
     3  import (
     4  	"unsafe"
     5  )
     6  
     7  type Slice struct {
     8  	Ptr unsafe.Pointer
     9  	Len int
    10  	Cap int
    11  }
    12  
    13  func Struct[E any](s []E) Slice {
    14  	return *(*Slice)(unsafe.Pointer(&s))
    15  }
    16  
    17  func StructP[E any](sp *[]E) *Slice {
    18  	return (*Slice)(unsafe.Pointer(sp))
    19  }
    20  
    21  func StructTo[E any](s Slice) (es []E) {
    22  	*(*Slice)(unsafe.Pointer(&es)) = s
    23  	return
    24  }
    25  
    26  func Build[E any](ptr unsafe.Pointer, len, cap int) (s []E) {
    27  	*(*Slice)(unsafe.Pointer(&s)) = Slice{Ptr: ptr, Len: len, Cap: cap}
    28  	return
    29  }
    30  
    31  func Convert[EI, EO any](s []EI, len, cap int) (os []EO) {
    32  	*(*Slice)(unsafe.Pointer(&os)) = Slice{Ptr: (*Slice)(unsafe.Pointer(&s)).Ptr, Len: len, Cap: cap}
    33  	return
    34  }
    35  
    36  func String(bs []byte) string {
    37  	return *(*string)(unsafe.Pointer(&bs))
    38  }
    39  
    40  func Pointer[E any](s []E) unsafe.Pointer {
    41  	return (*Slice)(unsafe.Pointer(&s)).Ptr
    42  }
    43  
    44  func In[E any](p *E, s []E) bool {
    45  	if len(s) == 0 {
    46  		return false
    47  	}
    48  	up := uintptr(unsafe.Pointer(p))
    49  	return up >= uintptr(unsafe.Pointer(&s[0])) &&
    50  		up <= uintptr(unsafe.Pointer(&s[len(s)-1]))
    51  }
    52  
    53  func Merge[E any](ss ...[]E) []E {
    54  	if len(ss) == 0 {
    55  		return nil
    56  	}
    57  	var e E
    58  	es := unsafe.Sizeof(e)
    59  	p := (*Slice)(unsafe.Pointer(&ss[0])).Ptr
    60  	sp := uintptr(p)
    61  	cp := sp + uintptr(cap(ss[0]))*es
    62  	lp := sp + uintptr(len(ss[0]))*es
    63  
    64  	min, maxC, maxL := sp, cp, lp
    65  	for _, s := range ss[1:] {
    66  		up := (*Slice)(unsafe.Pointer(&s)).Ptr
    67  		if sp = uintptr(up); sp > maxC {
    68  			return nil
    69  		} else if sp < min {
    70  			min = sp
    71  			p = up
    72  		}
    73  		if cp = sp + uintptr(cap(s))*es; cp < min {
    74  			return nil
    75  		} else if cp > maxC {
    76  			maxC = cp
    77  		}
    78  		if lp = sp + uintptr(len(s))*es; lp > maxL {
    79  			maxL = lp
    80  		}
    81  	}
    82  	return Build[E](p, int((maxL-min)/es), int((maxC-min)/es))
    83  }