-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathunsafe.go
46 lines (40 loc) · 1.27 KB
/
unsafe.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
package generic
import (
"unsafe"
)
// UnsafeRawBytes returns the raw bytes behind the object
func UnsafeRawBytes[T any](v *T) []byte {
return unsafe.Slice((*byte)(unsafe.Pointer(v)), unsafe.Sizeof(*v))
}
// UnsafeRawBytesOffset returns the raw bytes behind an object, skipping the
// first few fields
func UnsafeRawBytesOffset[T, S any](v *T, memberPtr *S) []byte {
offset := uintptr(unsafe.Pointer(memberPtr))
base := uintptr(unsafe.Pointer(v))
size := uintptr(unsafe.Sizeof(*v))
diff := offset - base
if size > offset {
panic("Invalid offset")
}
sliceBase := unsafe.Pointer(memberPtr)
sliceLen := int(size - diff)
return unsafe.Slice((*byte)(sliceBase), sliceLen)
}
// UnsafeSliceBytes takes a slice of any type and reinterprets it as a slice of
// bytes
func UnsafeSliceBytes[T any](v []T) []byte {
if len(v) == 0 {
return nil
}
size := int(unsafe.Sizeof(v[0])) * len(v)
data := (*byte)(unsafe.Pointer(&v[0]))
return unsafe.Slice(data, uintptr(size))
}
// UnsafeStringBytes converts a string to a byte slice without copying
func UnsafeStringBytes(s string) []byte {
return unsafe.Slice(unsafe.StringData(s), len(s))
}
// UnsafeString converts a byte slice to a string without copying
func UnsafeString(b []byte) string {
return unsafe.String(unsafe.SliceData(b), len(b))
}