Generic slice unmarshal fn
This commit is contained in:
@@ -63,3 +63,14 @@ func Stride(ptr unsafe.Pointer, size uintptr, offset int) unsafe.Pointer {
|
||||
// https://github.com/golang/go/issues/40481
|
||||
return unsafe.Pointer(uintptr(ptr) + uintptr(int(size)*offset))
|
||||
}
|
||||
|
||||
type Slice struct {
|
||||
Data unsafe.Pointer
|
||||
Len int
|
||||
Cap int
|
||||
}
|
||||
|
||||
type iface struct {
|
||||
typ unsafe.Pointer
|
||||
ptr unsafe.Pointer
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
//go:build go1.18
|
||||
// +build go1.18
|
||||
|
||||
package danger
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func ExtendSlice(t reflect.Type, s *Slice, n int) Slice {
|
||||
arrayType := reflect.ArrayOf(n, t.Elem())
|
||||
arrayData := reflect.New(arrayType)
|
||||
reflect.Copy(arrayData.Elem(), reflect.NewAt(t, unsafe.Pointer(s)).Elem())
|
||||
return Slice{
|
||||
Data: unsafe.Pointer(arrayData.Pointer()),
|
||||
Len: s.Len,
|
||||
Cap: n,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
//go:build !go1.18
|
||||
// +build !go1.18
|
||||
|
||||
package danger
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
//go:linkname unsafe_NewArray reflect.unsafe_NewArray
|
||||
func unsafe_NewArray(rtype unsafe.Pointer, length int) unsafe.Pointer
|
||||
|
||||
//go:linkname typedslicecopy reflect.typedslicecopy
|
||||
//go:noescape
|
||||
func typedslicecopy(elemType unsafe.Pointer, dst, src Slice) int
|
||||
|
||||
func ExtendSlice(t reflect.Type, s *Slice, n int) Slice {
|
||||
elemTypeRef := t.Elem()
|
||||
elemTypePtr := ((*iface)(unsafe.Pointer(&elemTypeRef))).ptr
|
||||
|
||||
d := Slice{
|
||||
Data: unsafe_NewArray(elemTypePtr, n),
|
||||
Len: s.Len,
|
||||
Cap: n,
|
||||
}
|
||||
|
||||
typedslicecopy(elemTypePtr, d, *s)
|
||||
return d
|
||||
}
|
||||
Reference in New Issue
Block a user