-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathabi.go
69 lines (64 loc) · 1.99 KB
/
abi.go
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
package mock
import (
"reflect"
"unsafe"
)
//go:linkname addReflectOff reflect.addReflectOff
func addReflectOff(ptr unsafe.Pointer) int32
type abiMethod struct {
Name int32 // name of method
Mtyp int32 // method type (without receiver)
Ifn int32 // fn used in interface call (one-word receiver)
Tfn int32 // fn used for normal method call
}
func (m *abiMethod) setFn(fn any) {
off := addReflectOff(unsafe.Pointer(reflect.ValueOf(fn).Pointer()))
//m.Tfn = off
m.Ifn = off
}
func getAbiMethods(typ reflect.Type) []abiMethod {
if typ.Kind() != reflect.Struct {
panic("not struct kind: " + typ.Kind().String())
}
type Type struct {
Size_ uintptr
PtrBytes uintptr // number of (prefix) bytes in the type that can contain pointers
Hash uint32 // hash of type; avoids computation in hash tables
TFlag uint8 // extra type information flags
Align_ uint8 // alignment of variable with this type
FieldAlign_ uint8 // alignment of struct field with this type
Kind_ uint8 // enumeration for C
Equal func(unsafe.Pointer, unsafe.Pointer) bool
GCData *byte
Str int32 // string form
PtrToThis int32 // type for pointer to this type, may be zero
}
type UncommonType struct {
PkgPath int32 // import path; empty for built-in types like int, string
Mcount uint16 // number of methods
Xcount uint16 // number of exported methods
Moff uint32 // offset from this uncommontype to [mcount]Method
_ uint32 // unused
}
type StructField struct {
Name *byte // name is always non-empty
Typ *Type // type of field
Offset uintptr // byte offset of field
}
type StructType struct {
Type
PkgPath *byte
Fields []StructField
}
type StructTypeUncommon struct {
StructType
u UncommonType
}
t := (*(*[2]unsafe.Pointer)(unsafe.Pointer(&typ)))[1]
u := &(*StructTypeUncommon)(t).u
if u.Mcount == 0 {
return nil
}
m := unsafe.Add(unsafe.Pointer(u), u.Moff)
return unsafe.Slice((*abiMethod)(m), u.Mcount)
}