xx/xx.go
2026-01-09 16:54:10 -07:00

60 lines
1.4 KiB
Go

package xx
import (
"runtime"
"strings"
"unsafe"
"git.brut.systems/judah/xx/mem"
)
// Copy copies src number of bytes into dst.
// Returns dst.
//
// Copy panics if src is smaller than dst.
func Copy[TDst any, TSrc any](dst *TDst, src *TSrc) *TDst {
if mem.Sizeof[TSrc]() < mem.Sizeof[TDst]() {
panic("copy: size of src must be >= dst")
}
mem.Copy(unsafe.Pointer(dst), unsafe.Pointer(src), mem.Sizeof[TDst]())
return dst
}
// Clone returns a newly allocated shallow copy of the given value.
func Clone[T any](value *T) *T {
return Copy(new(T), value)
}
// BoolUint converts a boolean to an integer.
func BoolUint(b bool) uint {
return uint(*(*uint8)(unsafe.Pointer(&b)))
}
// CallerLocation returns the source location of the function CallerLocation is called in.
func CallerLocation() (file string, line int) {
_, file, line, _ = runtime.Caller(2)
// @todo: I'm sure there's a better way to do this
// Special-case when CallerLocation is called from main
if strings.Contains(file, "runtime") && strings.Contains(file, "proc.go") {
_, file, line, _ = runtime.Caller(1)
}
return
}
// HashLocation returns a hash of file and line, most likely returned from [CallerLocation].
func HashLocation(file string, line int) uint64 {
const (
FNV64_PRIME uint64 = 0x100000001B3
FNV64_BIAS uint64 = 0xCBF29CE484222325
)
h := FNV64_BIAS
for _, c := range file {
h = (h ^ uint64(c)) * FNV64_PRIME
}
h = (h ^ uint64(line)) * FNV64_PRIME
return h
}