summaryrefslogtreecommitdiff
path: root/vendor/codeberg.org/gruf/go-xunsafe/reflect.go
blob: de40b2c89605ae35b37d38b35f10d76a6fa0692d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
//go:build go1.24 && !go1.26

package xunsafe

import (
	"reflect"
	"unsafe"
)

// see: go/src/reflect/value.go
type Reflect_flag uintptr

const (
	// see: go/src/reflect/value.go
	Reflect_flagKindWidth                = 5 // there are 27 kinds
	Reflect_flagKindMask    Reflect_flag = 1<<Reflect_flagKindWidth - 1
	Reflect_flagStickyRO    Reflect_flag = 1 << 5
	Reflect_flagEmbedRO     Reflect_flag = 1 << 6
	Reflect_flagIndir       Reflect_flag = 1 << 7
	Reflect_flagAddr        Reflect_flag = 1 << 8
	Reflect_flagMethod      Reflect_flag = 1 << 9
	Reflect_flagMethodShift              = 10
	Reflect_flagRO          Reflect_flag = Reflect_flagStickyRO | Reflect_flagEmbedRO
)

// ReflectIfaceElemFlags returns the reflect_flag expected of an unboxed interface element of type.
//
// see: go/src/reflect/value.go unpackElem()
func ReflectIfaceElemFlags(elemType reflect.Type) Reflect_flag {
	if elemType == nil {
		return 0
	}
	flags := Reflect_flag(Abi_Type_Kind(elemType))
	if Abi_Type_IfaceIndir(elemType) {
		flags |= Reflect_flagIndir
	}
	return flags
}

// ReflectPointerElemFlags returns the reflect_flag expected of a dereferenced pointer element of type.
//
// see: go/src/reflect/value.go Value.Elem()
func ReflectPointerElemFlags(ptrFlags Reflect_flag, elemType reflect.Type) Reflect_flag {
	return ptrFlags | Reflect_flagIndir | Reflect_flagAddr | Reflect_flag(Abi_Type_Kind(elemType))
}

// ReflectArrayElemFlags returns the reflect_flag expected of an element of type in an array.
//
// see: go/src/reflect/value.go Value.Index()
func ReflectArrayElemFlags(arrayFlags Reflect_flag, elemType reflect.Type) Reflect_flag {
	return arrayFlags&(Reflect_flagIndir|Reflect_flagAddr) | Reflect_flag(Abi_Type_Kind(elemType))
}

// reflect_slice_elem_flags returns the reflect_flag expected of a slice element of type.
//
// see: go/src/reflect/value.go Value.Index()
func ReflectSliceElemFlags(elemType reflect.Type) Reflect_flag {
	return Reflect_flagAddr | Reflect_flagIndir | Reflect_flag(Abi_Type_Kind(elemType))
}

// ReflectStructFieldFlags returns the reflect_flag expected of a struct field of type.
//
// see: go/src/reflect/value.go Value.Field()
func ReflectStructFieldFlags(structFlags Reflect_flag, fieldType reflect.Type) Reflect_flag {
	return structFlags&(Reflect_flagIndir|Reflect_flagAddr) | Reflect_flag(Abi_Type_Kind(fieldType))
}

// ReflectMapKeyFlags returns the reflect_flag expected of a map key of type.
//
// see: go/src/reflect/map_swiss.go MapIter.Key()
func ReflectMapKeyFlags(keyType reflect.Type) Reflect_flag {
	return Reflect_flag(Abi_Type_Kind(keyType))
}

// ReflectMapElemFlags returns the reflect_flag expected of a map element of type.
//
// see: go/src/reflect/map_swiss.go MapIter.Value()
func ReflectMapElemFlags(elemType reflect.Type) Reflect_flag {
	return Reflect_flag(Abi_Type_Kind(elemType))
}

// reflect_Value is a copy of the memory layout of reflect.Value{}.
//
// see: go/src/reflect/value.go
type reflect_Value struct {
	typ_ unsafe.Pointer
	ptr  unsafe.Pointer
	Reflect_flag
}

func init() {
	if unsafe.Sizeof(reflect_Value{}) != unsafe.Sizeof(reflect.Value{}) {
		panic("reflect_Value{} not in sync with reflect.Value{}")
	}
}

// reflect_type_data returns the .word from the reflect.Type{} cast
// as the reflect.nonEmptyInterface{}, which itself will be a pointer
// to the actual abi.Type{} that this reflect.Type{} is wrapping.
func ReflectTypeData(t reflect.Type) unsafe.Pointer {
	return (*Abi_NonEmptyInterface)(unsafe.Pointer(&t)).Data
}

// BuildReflectValue manually builds a reflect.Value{} by setting the internal field members.
func BuildReflectValue(rtype reflect.Type, data unsafe.Pointer, flags Reflect_flag) reflect.Value {
	return *(*reflect.Value)(unsafe.Pointer(&reflect_Value{ReflectTypeData(rtype), data, flags}))
}

// Reflect_MapIter is a copy of the memory layout of reflect.MapIter{}.
//
// see: go/src/reflect/map_swiss.go
type Reflect_MapIter struct {
	m     reflect.Value
	hiter maps_Iter
}

// maps_Iter is a copy of the memory layout of maps.Iter{}.
//
// see: go/src/internal/runtime/maps/table.go
type maps_Iter struct {
	key  unsafe.Pointer
	elem unsafe.Pointer
	_    uintptr
	_    uintptr
	_    uint64
	_    uint64
	_    uint64
	_    uint8
	_    int
	_    uintptr
	_    struct{ _ unsafe.Pointer }
	_    uint64
}

func init() {
	if unsafe.Sizeof(Reflect_MapIter{}) != unsafe.Sizeof(reflect.MapIter{}) {
		panic("Reflect_MapIter{} not in sync with reflect.MapIter{}")
	}
}

// GetMapIter creates a new map iterator from value,
// skipping the initial v.MapRange() type checking.
func GetMapIter(v reflect.Value) *reflect.MapIter {
	var i Reflect_MapIter
	i.m = v
	return (*reflect.MapIter)(unsafe.Pointer(&i))
}

// Map_Key returns ptr to current map key in iter.
func Map_Key(i *reflect.MapIter) unsafe.Pointer {
	return (*Reflect_MapIter)(unsafe.Pointer(i)).hiter.key
}

// Map_Elem returns ptr to current map element in iter.
func Map_Elem(i *reflect.MapIter) unsafe.Pointer {
	return (*Reflect_MapIter)(unsafe.Pointer(i)).hiter.elem
}