-
Notifications
You must be signed in to change notification settings - Fork 5
/
slice_copier.go
58 lines (47 loc) · 1.45 KB
/
slice_copier.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
package copy
import (
"fmt"
"reflect"
"unsafe"
)
type SliceCopier struct {
BaseCopier
copier func(dst, src unsafe.Pointer)
dstSize uintptr // Size of the destination element
srcSize uintptr // Size of the source element
}
func NewSliceCopier(c *Copiers) *SliceCopier {
copier := &SliceCopier{BaseCopier: NewBaseCopier(c)}
return copier
}
func (c *SliceCopier) init(dst, src reflect.Type) {
c.BaseCopier.init(dst, src)
c.copier = c.getCopierFunc(dst.Elem(), src.Elem(), 0, 0)
if c.copier == nil && !c.options.Skip {
panic(fmt.Errorf(`slice element of type «%s» is not assignable to slice element of type «%s»`, src.String(), dst.String()))
}
c.dstSize = dst.Elem().Size()
c.srcSize = src.Elem().Size()
}
// Copy copies the contents of src into dst. Dst and src each must be a pointer to struct.
func (c *SliceCopier) Copy(dst, src interface{}) {
dstType, dstPtr := DataOf(dst)
srcType, srcPtr := DataOf(src)
if c.src.Check(srcType) {
panic("source expected type " + c.src.Name + ", but has " + reflect.TypeOf(src).String())
}
if c.dst.Check(dstType) {
panic("destination expected type " + c.dst.Name + ", but has " + reflect.TypeOf(dst).String())
}
c.copy(dstPtr, srcPtr)
}
func (c *SliceCopier) copy(dst, src unsafe.Pointer) {
if c.copier == nil {
return
}
srcSlice := sliceAt(src, c.srcSize)
dstSlice := makeSliceAt(dst, c.dstSize, srcSlice.Len)
for i := 0; i < srcSlice.Len; i++ {
c.copier(dstSlice.Index(i), srcSlice.Index(i))
}
}