mirror of
https://github.com/ceph/ceph-csi.git
synced 2025-03-09 17:09:29 +00:00
Several packages are only used while running the e2e suite. These packages are less important to update, as the they can not influence the final executable that is part of the Ceph-CSI container-image. By moving these dependencies out of the main Ceph-CSI go.mod, it is easier to identify if a reported CVE affects Ceph-CSI, or only the testing (like most of the Kubernetes CVEs). Signed-off-by: Niels de Vos <ndevos@ibm.com>
301 lines
7.2 KiB
Go
301 lines
7.2 KiB
Go
package reflect2
|
|
|
|
import (
|
|
"reflect"
|
|
"runtime"
|
|
"sync"
|
|
"unsafe"
|
|
)
|
|
|
|
type Type interface {
|
|
Kind() reflect.Kind
|
|
// New return pointer to data of this type
|
|
New() interface{}
|
|
// UnsafeNew return the allocated space pointed by unsafe.Pointer
|
|
UnsafeNew() unsafe.Pointer
|
|
// PackEFace cast a unsafe pointer to object represented pointer
|
|
PackEFace(ptr unsafe.Pointer) interface{}
|
|
// Indirect dereference object represented pointer to this type
|
|
Indirect(obj interface{}) interface{}
|
|
// UnsafeIndirect dereference pointer to this type
|
|
UnsafeIndirect(ptr unsafe.Pointer) interface{}
|
|
// Type1 returns reflect.Type
|
|
Type1() reflect.Type
|
|
Implements(thatType Type) bool
|
|
String() string
|
|
RType() uintptr
|
|
// interface{} of this type has pointer like behavior
|
|
LikePtr() bool
|
|
IsNullable() bool
|
|
IsNil(obj interface{}) bool
|
|
UnsafeIsNil(ptr unsafe.Pointer) bool
|
|
Set(obj interface{}, val interface{})
|
|
UnsafeSet(ptr unsafe.Pointer, val unsafe.Pointer)
|
|
AssignableTo(anotherType Type) bool
|
|
}
|
|
|
|
type ListType interface {
|
|
Type
|
|
Elem() Type
|
|
SetIndex(obj interface{}, index int, elem interface{})
|
|
UnsafeSetIndex(obj unsafe.Pointer, index int, elem unsafe.Pointer)
|
|
GetIndex(obj interface{}, index int) interface{}
|
|
UnsafeGetIndex(obj unsafe.Pointer, index int) unsafe.Pointer
|
|
}
|
|
|
|
type ArrayType interface {
|
|
ListType
|
|
Len() int
|
|
}
|
|
|
|
type SliceType interface {
|
|
ListType
|
|
MakeSlice(length int, cap int) interface{}
|
|
UnsafeMakeSlice(length int, cap int) unsafe.Pointer
|
|
Grow(obj interface{}, newLength int)
|
|
UnsafeGrow(ptr unsafe.Pointer, newLength int)
|
|
Append(obj interface{}, elem interface{})
|
|
UnsafeAppend(obj unsafe.Pointer, elem unsafe.Pointer)
|
|
LengthOf(obj interface{}) int
|
|
UnsafeLengthOf(ptr unsafe.Pointer) int
|
|
SetNil(obj interface{})
|
|
UnsafeSetNil(ptr unsafe.Pointer)
|
|
Cap(obj interface{}) int
|
|
UnsafeCap(ptr unsafe.Pointer) int
|
|
}
|
|
|
|
type StructType interface {
|
|
Type
|
|
NumField() int
|
|
Field(i int) StructField
|
|
FieldByName(name string) StructField
|
|
FieldByIndex(index []int) StructField
|
|
FieldByNameFunc(match func(string) bool) StructField
|
|
}
|
|
|
|
type StructField interface {
|
|
Offset() uintptr
|
|
Name() string
|
|
PkgPath() string
|
|
Type() Type
|
|
Tag() reflect.StructTag
|
|
Index() []int
|
|
Anonymous() bool
|
|
Set(obj interface{}, value interface{})
|
|
UnsafeSet(obj unsafe.Pointer, value unsafe.Pointer)
|
|
Get(obj interface{}) interface{}
|
|
UnsafeGet(obj unsafe.Pointer) unsafe.Pointer
|
|
}
|
|
|
|
type MapType interface {
|
|
Type
|
|
Key() Type
|
|
Elem() Type
|
|
MakeMap(cap int) interface{}
|
|
UnsafeMakeMap(cap int) unsafe.Pointer
|
|
SetIndex(obj interface{}, key interface{}, elem interface{})
|
|
UnsafeSetIndex(obj unsafe.Pointer, key unsafe.Pointer, elem unsafe.Pointer)
|
|
TryGetIndex(obj interface{}, key interface{}) (interface{}, bool)
|
|
GetIndex(obj interface{}, key interface{}) interface{}
|
|
UnsafeGetIndex(obj unsafe.Pointer, key unsafe.Pointer) unsafe.Pointer
|
|
Iterate(obj interface{}) MapIterator
|
|
UnsafeIterate(obj unsafe.Pointer) MapIterator
|
|
}
|
|
|
|
type MapIterator interface {
|
|
HasNext() bool
|
|
Next() (key interface{}, elem interface{})
|
|
UnsafeNext() (key unsafe.Pointer, elem unsafe.Pointer)
|
|
}
|
|
|
|
type PtrType interface {
|
|
Type
|
|
Elem() Type
|
|
}
|
|
|
|
type InterfaceType interface {
|
|
NumMethod() int
|
|
}
|
|
|
|
type Config struct {
|
|
UseSafeImplementation bool
|
|
}
|
|
|
|
type API interface {
|
|
TypeOf(obj interface{}) Type
|
|
Type2(type1 reflect.Type) Type
|
|
}
|
|
|
|
var ConfigUnsafe = Config{UseSafeImplementation: false}.Froze()
|
|
var ConfigSafe = Config{UseSafeImplementation: true}.Froze()
|
|
|
|
type frozenConfig struct {
|
|
useSafeImplementation bool
|
|
cache *sync.Map
|
|
}
|
|
|
|
func (cfg Config) Froze() *frozenConfig {
|
|
return &frozenConfig{
|
|
useSafeImplementation: cfg.UseSafeImplementation,
|
|
cache: new(sync.Map),
|
|
}
|
|
}
|
|
|
|
func (cfg *frozenConfig) TypeOf(obj interface{}) Type {
|
|
cacheKey := uintptr(unpackEFace(obj).rtype)
|
|
typeObj, found := cfg.cache.Load(cacheKey)
|
|
if found {
|
|
return typeObj.(Type)
|
|
}
|
|
return cfg.Type2(reflect.TypeOf(obj))
|
|
}
|
|
|
|
func (cfg *frozenConfig) Type2(type1 reflect.Type) Type {
|
|
if type1 == nil {
|
|
return nil
|
|
}
|
|
cacheKey := uintptr(unpackEFace(type1).data)
|
|
typeObj, found := cfg.cache.Load(cacheKey)
|
|
if found {
|
|
return typeObj.(Type)
|
|
}
|
|
type2 := cfg.wrapType(type1)
|
|
cfg.cache.Store(cacheKey, type2)
|
|
return type2
|
|
}
|
|
|
|
func (cfg *frozenConfig) wrapType(type1 reflect.Type) Type {
|
|
safeType := safeType{Type: type1, cfg: cfg}
|
|
switch type1.Kind() {
|
|
case reflect.Struct:
|
|
if cfg.useSafeImplementation {
|
|
return &safeStructType{safeType}
|
|
}
|
|
return newUnsafeStructType(cfg, type1)
|
|
case reflect.Array:
|
|
if cfg.useSafeImplementation {
|
|
return &safeSliceType{safeType}
|
|
}
|
|
return newUnsafeArrayType(cfg, type1)
|
|
case reflect.Slice:
|
|
if cfg.useSafeImplementation {
|
|
return &safeSliceType{safeType}
|
|
}
|
|
return newUnsafeSliceType(cfg, type1)
|
|
case reflect.Map:
|
|
if cfg.useSafeImplementation {
|
|
return &safeMapType{safeType}
|
|
}
|
|
return newUnsafeMapType(cfg, type1)
|
|
case reflect.Ptr, reflect.Chan, reflect.Func:
|
|
if cfg.useSafeImplementation {
|
|
return &safeMapType{safeType}
|
|
}
|
|
return newUnsafePtrType(cfg, type1)
|
|
case reflect.Interface:
|
|
if cfg.useSafeImplementation {
|
|
return &safeMapType{safeType}
|
|
}
|
|
if type1.NumMethod() == 0 {
|
|
return newUnsafeEFaceType(cfg, type1)
|
|
}
|
|
return newUnsafeIFaceType(cfg, type1)
|
|
default:
|
|
if cfg.useSafeImplementation {
|
|
return &safeType
|
|
}
|
|
return newUnsafeType(cfg, type1)
|
|
}
|
|
}
|
|
|
|
func TypeOf(obj interface{}) Type {
|
|
return ConfigUnsafe.TypeOf(obj)
|
|
}
|
|
|
|
func TypeOfPtr(obj interface{}) PtrType {
|
|
return TypeOf(obj).(PtrType)
|
|
}
|
|
|
|
func Type2(type1 reflect.Type) Type {
|
|
if type1 == nil {
|
|
return nil
|
|
}
|
|
return ConfigUnsafe.Type2(type1)
|
|
}
|
|
|
|
func PtrTo(typ Type) Type {
|
|
return Type2(reflect.PtrTo(typ.Type1()))
|
|
}
|
|
|
|
func PtrOf(obj interface{}) unsafe.Pointer {
|
|
return unpackEFace(obj).data
|
|
}
|
|
|
|
func RTypeOf(obj interface{}) uintptr {
|
|
return uintptr(unpackEFace(obj).rtype)
|
|
}
|
|
|
|
func IsNil(obj interface{}) bool {
|
|
if obj == nil {
|
|
return true
|
|
}
|
|
return unpackEFace(obj).data == nil
|
|
}
|
|
|
|
func IsNullable(kind reflect.Kind) bool {
|
|
switch kind {
|
|
case reflect.Ptr, reflect.Map, reflect.Chan, reflect.Func, reflect.Slice, reflect.Interface:
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
func likePtrKind(kind reflect.Kind) bool {
|
|
switch kind {
|
|
case reflect.Ptr, reflect.Map, reflect.Chan, reflect.Func:
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
func likePtrType(typ reflect.Type) bool {
|
|
if likePtrKind(typ.Kind()) {
|
|
return true
|
|
}
|
|
if typ.Kind() == reflect.Struct {
|
|
if typ.NumField() != 1 {
|
|
return false
|
|
}
|
|
return likePtrType(typ.Field(0).Type)
|
|
}
|
|
if typ.Kind() == reflect.Array {
|
|
if typ.Len() != 1 {
|
|
return false
|
|
}
|
|
return likePtrType(typ.Elem())
|
|
}
|
|
return false
|
|
}
|
|
|
|
// NoEscape hides a pointer from escape analysis. noescape is
|
|
// the identity function but escape analysis doesn't think the
|
|
// output depends on the input. noescape is inlined and currently
|
|
// compiles down to zero instructions.
|
|
// USE CAREFULLY!
|
|
//go:nosplit
|
|
func NoEscape(p unsafe.Pointer) unsafe.Pointer {
|
|
x := uintptr(p)
|
|
return unsafe.Pointer(x ^ 0)
|
|
}
|
|
|
|
func UnsafeCastString(str string) []byte {
|
|
bytes := make([]byte, 0)
|
|
stringHeader := (*reflect.StringHeader)(unsafe.Pointer(&str))
|
|
sliceHeader := (*reflect.SliceHeader)(unsafe.Pointer(&bytes))
|
|
sliceHeader.Data = stringHeader.Data
|
|
sliceHeader.Cap = stringHeader.Len
|
|
sliceHeader.Len = stringHeader.Len
|
|
runtime.KeepAlive(str)
|
|
return bytes
|
|
}
|