summaryrefslogtreecommitdiff
path: root/vendor/codeberg.org/gruf/go-kv/v2/format/abi.go
blob: b68d3cb7328072961df67c603e46218395edcf8d (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
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
//go:build go1.24 && !go1.26

package format

import (
	"reflect"
	"unsafe"
)

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
}

// pack_iface packs a new reflect.nonEmptyInterface{} using shielded
// itab and data pointer, returning a pointer for caller casting.
func pack_iface(itab uintptr, word unsafe.Pointer) unsafe.Pointer {
	return unsafe.Pointer(&abi_NonEmptyInterface{
		ITab: itab,
		Data: word,
	})
}

// get_iface_ITab generates a new value of given type,
// casts it to the generic param interface type, and
// returns the .itab portion of the reflect.nonEmptyInterface{}.
// this is useful for later calls to pack_iface for known type.
func get_iface_ITab[I any](t reflect.Type) uintptr {
	s := reflect.New(t).Elem().Interface().(I)
	i := (*abi_NonEmptyInterface)(unsafe.Pointer(&s))
	return i.ITab
}

// unpack_eface returns the .Data portion of an abi.EmptyInterface{}.
func unpack_eface(a any) unsafe.Pointer {
	return (*abi_EmptyInterface)(unsafe.Pointer((&a))).Data
}

// add returns the ptr addition of starting ptr and a delta.
func add(ptr unsafe.Pointer, delta uintptr) unsafe.Pointer {
	return unsafe.Pointer(uintptr(ptr) + delta)
}

// typeof is short-hand for reflect.TypeFor[T]().
func typeof[T any]() reflect.Type {
	return reflect.TypeFor[T]()
}

// 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

	// custom flag to indicate key types.
	flagKeyType = 1 << 10
)

// reflect_iface_elem_flags returns the reflect_flag expected of an unboxed interface element of type.
//
// see: go/src/reflect/value.go unpackElem()
func reflect_iface_elem_flags(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
}

// reflect_pointer_elem_flags returns the reflect_flag expected of a dereferenced pointer element of type.
//
// see: go/src/reflect/value.go Value.Elem()
func reflect_pointer_elem_flags(ptrFlags reflect_flag, elemType reflect.Type) reflect_flag {
	return ptrFlags | reflect_flagIndir | reflect_flagAddr | reflect_flag(abi_Type_Kind(elemType))
}

// reflect_array_elem_flags returns the reflect_flag expected of an element of type in an array.
//
// see: go/src/reflect/value.go Value.Index()
func reflect_array_elem_flags(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 reflect_slice_elem_flags(elemType reflect.Type) reflect_flag {
	return reflect_flagAddr | reflect_flagIndir | reflect_flag(abi_Type_Kind(elemType))
}

// reflect_struct_field_flags returns the reflect_flag expected of a struct field of type.
//
// see: go/src/reflect/value.go Value.Field()
func reflect_struct_field_flags(structFlags reflect_flag, fieldType reflect.Type) reflect_flag {
	return structFlags&(reflect_flagIndir|reflect_flagAddr) | reflect_flag(abi_Type_Kind(fieldType))
}

// reflect_map_key_flags returns the reflect_flag expected of a map key of type (with our own key type mask set).
//
// see: go/src/reflect/map_swiss.go MapIter.Key()
func reflect_map_key_flags(keyType reflect.Type) reflect_flag {
	return flagKeyType | reflect_flag(abi_Type_Kind(keyType))
}

// reflect_map_elem_flags returns the reflect_flag expected of a map element of type.
//
// see: go/src/reflect/map_swiss.go MapIter.Value()
func reflect_map_elem_flags(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 reflect_type_data(t reflect.Type) unsafe.Pointer {
	return (*abi_NonEmptyInterface)(unsafe.Pointer(&t)).Data
}

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

// 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
}

// 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
}

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

// map_iter creates a new map iterator from value,
// skipping the initial v.MapRange() type checking.
func map_iter(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
}

// 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
}