We'd like to do a zero-copy conversion of []byte to []uint64 where the underlying memory for the byte slice is properly aligned for N uint64 values. After looking at
(6) in the unsafe package documentation, I'm wondering if the code below is valid because I only use reflect.SliceHeader as pointers, and it seems to fit pattern 6.
package main
import (
"fmt"
"reflect"
"unsafe"
)
func byteToUint64(b []byte) (out []uint64, err error) {
inhdr := *(*reflect.SliceHeader)(unsafe.Pointer(&b))
if inhdr.Len % 8 != 0 {
err = fmt.Errorf("cannot convert non-aligned []byte length (%d) to []uint64", inhdr.Len)
return
}
if inhdr.Cap % 8 != 0 {
err = fmt.Errorf("cannot convert non-aligned []byte capacity (%d) to []uint64", inhdr.Cap)
return
}
outhdr := *(*reflect.SliceHeader)(unsafe.Pointer(&out))
outhdr.Len = inhdr.Len / 8
outhdr.Cap = inhdr.Cap / 8
outhdr.Data = inhdr.Data
out = *(*[]uint64)(unsafe.Pointer(&outhdr))
return
}
func main() {
b := make([]byte, 24)
u, err := byteToUint64(b)
if err != nil {
fmt.Println(err)
} else {
fmt.Printf("b: %v\n", b)
fmt.Printf("u: %v\n", u)
fmt.Printf("len(u) = %d, cap(u) = %d\n", len(u), cap(u))
u[0] = 15
fmt.Printf("Set u[0] to 15\n")
fmt.Printf("b: %v\n", b)
fmt.Printf("u: %v\n", u)
u[2] = 255
fmt.Printf("Set u[2] to 255\n")
fmt.Printf("b: %v\n", b)
fmt.Printf("u: %v\n", u)
}
}
b: [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
u: [0 0 0]
len(u) = 3, cap(u) = 3
Set u[0] to 15
b: [15 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
u: [15 0 0]
Set u[2] to 255
b: [15 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0]
u: [15 0 255]