-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathinterface_copier.go
More file actions
101 lines (81 loc) · 2.15 KB
/
interface_copier.go
File metadata and controls
101 lines (81 loc) · 2.15 KB
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
package deepcopy
import (
"reflect"
"unsafe"
"github.com/modern-go/reflect2"
)
type efaceCopier struct {
}
var efaceCopierPtr = &efaceCopier{}
func (i *efaceCopier) Copy(src, dst unsafe.Pointer) {
srcEface := *((*interface{})(src))
dstEfacePtr := (*eface)(dst)
if srcEface == nil {
*dstEfacePtr = eface{nil, nil}
return
}
if reflect2.IsNil(srcEface) {
*dstEfacePtr = eface{(*eface)(src).rtype, nil}
return
}
srcType := reflect2.TypeOf(srcEface)
if srcType.Kind() != reflect.Ptr {
*dstEfacePtr = eface{(*eface)(src).rtype, srcType.UnsafeNew()}
CopierOf(srcType).Copy((*eface)(src).data, (*eface)(dst).data)
return
}
ptrElemType := srcType.(*reflect2.UnsafePtrType).Elem()
*dstEfacePtr = eface{(*eface)(src).rtype, ptrElemType.UnsafeNew()}
CopierOf(ptrElemType).Copy((*eface)(src).data, (*eface)(dst).data)
}
func createCopierOfEface(typ reflect2.Type) Copier {
_, ok := typ.(*reflect2.UnsafeEFaceType)
if !ok {
return nil
}
return efaceCopierPtr
}
type eface struct {
rtype unsafe.Pointer
data unsafe.Pointer
}
type ifaceCopier struct {
valType *reflect2.UnsafeIFaceType
}
func (i *ifaceCopier) Copy(src, dst unsafe.Pointer) {
if i.valType.UnsafeIsNil(src) {
i.valType.UnsafeSet(dst, i.valType.UnsafeNew())
return
}
srcEface := i.valType.UnsafeIndirect(src)
srcType := reflect2.TypeOf(srcEface)
if reflect2.IsNil(srcEface) {
i.valType.UnsafeSet(dst, unsafe.Pointer(&iface{(*iface)(src).itab, nil}))
return
}
if srcType.Kind() == reflect.Ptr {
ptrElemType := srcType.(*reflect2.UnsafePtrType).Elem()
i.valType.UnsafeSet(dst, unsafe.Pointer(&iface{(*iface)(src).itab, ptrElemType.UnsafeNew()}))
CopierOf(ptrElemType).Copy((*iface)(src).data, (*iface)(dst).data)
return
}
i.valType.UnsafeSet(dst, unsafe.Pointer(&iface{(*iface)(src).itab, srcType.UnsafeNew()}))
CopierOf(srcType).Copy((*iface)(src).data, (*iface)(dst).data)
}
func createCopierOfiface(typ reflect2.Type) Copier {
ifaceTyp, ok := typ.(*reflect2.UnsafeIFaceType)
if !ok {
return nil
}
return &ifaceCopier{
ifaceTyp,
}
}
type iface struct {
itab *itab
data unsafe.Pointer
}
type itab struct {
ignore unsafe.Pointer
rtype unsafe.Pointer
}