mirror of
https://github.com/superseriousbusiness/gotosocial.git
synced 2025-10-29 17:12:26 -05:00
110 lines
2.9 KiB
Go
110 lines
2.9 KiB
Go
|
|
//go:build go1.24 && !go1.26
|
||
|
|
|
||
|
|
package xunsafe
|
||
|
|
|
||
|
|
import (
|
||
|
|
"reflect"
|
||
|
|
"unsafe"
|
||
|
|
)
|
||
|
|
|
||
|
|
func init() {
|
||
|
|
// TypeOf(reflect.Type{}) == *struct{ abi.Type{} }
|
||
|
|
t := reflect.TypeOf(reflect.TypeOf(0)).Elem()
|
||
|
|
if t.Size() != unsafe.Sizeof(Abi_Type{}) {
|
||
|
|
panic("Abi_Type{} not in sync with abi.Type{}")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
const (
|
||
|
|
// see: go/src/internal/abi/type.go
|
||
|
|
Abi_KindDirectIface uint8 = 1 << 5
|
||
|
|
Abi_KindMask uint8 = (1 << 5) - 1
|
||
|
|
)
|
||
|
|
|
||
|
|
// Abi_Type is a copy of the memory layout of abi.Type{}.
|
||
|
|
//
|
||
|
|
// see: go/src/internal/abi/type.go
|
||
|
|
type Abi_Type struct {
|
||
|
|
_ uintptr
|
||
|
|
PtrBytes uintptr
|
||
|
|
_ uint32
|
||
|
|
_ uint8
|
||
|
|
_ uint8
|
||
|
|
_ uint8
|
||
|
|
Kind_ uint8
|
||
|
|
_ func(unsafe.Pointer, unsafe.Pointer) bool
|
||
|
|
_ *byte
|
||
|
|
_ int32
|
||
|
|
_ int32
|
||
|
|
}
|
||
|
|
|
||
|
|
// Abi_EmptyInterface is a copy of the memory layout of abi.EmptyInterface{},
|
||
|
|
// which is to say also the memory layout of any method-less interface.
|
||
|
|
//
|
||
|
|
// see: go/src/internal/abi/iface.go
|
||
|
|
type Abi_EmptyInterface struct {
|
||
|
|
Type *Abi_Type
|
||
|
|
Data unsafe.Pointer
|
||
|
|
}
|
||
|
|
|
||
|
|
// Abi_NonEmptyInterface is a copy of the memory layout of abi.NonEmptyInterface{},
|
||
|
|
// which is to say also the memory layout of any interface containing method(s).
|
||
|
|
//
|
||
|
|
// see: go/src/internal/abi/iface.go on 1.25+
|
||
|
|
// see: go/src/reflect/value.go on 1.24
|
||
|
|
type Abi_NonEmptyInterface struct {
|
||
|
|
ITab uintptr
|
||
|
|
Data unsafe.Pointer
|
||
|
|
}
|
||
|
|
|
||
|
|
// see: go/src/internal/abi/type.go Type.Kind()
|
||
|
|
func Abi_Type_Kind(t reflect.Type) uint8 {
|
||
|
|
iface := (*Abi_NonEmptyInterface)(unsafe.Pointer(&t))
|
||
|
|
atype := (*Abi_Type)(unsafe.Pointer(iface.Data))
|
||
|
|
return atype.Kind_ & Abi_KindMask
|
||
|
|
}
|
||
|
|
|
||
|
|
// see: go/src/internal/abi/type.go Type.IfaceIndir()
|
||
|
|
func Abi_Type_IfaceIndir(t reflect.Type) bool {
|
||
|
|
iface := (*Abi_NonEmptyInterface)(unsafe.Pointer(&t))
|
||
|
|
atype := (*Abi_Type)(unsafe.Pointer(iface.Data))
|
||
|
|
return atype.Kind_&Abi_KindDirectIface == 0
|
||
|
|
}
|
||
|
|
|
||
|
|
// PackIface packs a new reflect.nonEmptyInterface{} using shielded
|
||
|
|
// itab and data pointer, returning a pointer for caller casting.
|
||
|
|
func PackIface(itab uintptr, word unsafe.Pointer) unsafe.Pointer {
|
||
|
|
return unsafe.Pointer(&Abi_NonEmptyInterface{
|
||
|
|
ITab: itab,
|
||
|
|
Data: word,
|
||
|
|
})
|
||
|
|
}
|
||
|
|
|
||
|
|
// GetIfaceITab generates a new value of given type,
|
||
|
|
// casts it to the generic param interface type, and
|
||
|
|
// returns the .itab portion of the abi.NonEmptyInterface{}.
|
||
|
|
// this is useful for later calls to PackIface for known type.
|
||
|
|
func GetIfaceITab[I any](t reflect.Type) uintptr {
|
||
|
|
s := reflect.New(t).Elem().Interface().(I)
|
||
|
|
i := (*Abi_NonEmptyInterface)(unsafe.Pointer(&s))
|
||
|
|
return i.ITab
|
||
|
|
}
|
||
|
|
|
||
|
|
// UnpackEface returns the .Data portion of an abi.EmptyInterface{}.
|
||
|
|
func UnpackEface(a any) unsafe.Pointer {
|
||
|
|
return (*Abi_EmptyInterface)(unsafe.Pointer((&a))).Data
|
||
|
|
}
|
||
|
|
|
||
|
|
// see: go/src/internal/unsafeheader/unsafeheader.go
|
||
|
|
type Unsafeheader_Slice struct {
|
||
|
|
Data unsafe.Pointer
|
||
|
|
Len int
|
||
|
|
Cap int
|
||
|
|
}
|
||
|
|
|
||
|
|
// see: go/src/internal/unsafeheader/unsafeheader.go
|
||
|
|
type Unsafeheader_String struct {
|
||
|
|
Data unsafe.Pointer
|
||
|
|
Len int
|
||
|
|
}
|