Skip to content

Commit 1885609

Browse files
authored
Merge pull request #180 from driventokill/issue/170
fix: several issues while copy with custom converter
2 parents 20cee7e + 780b83e commit 1885609

File tree

2 files changed

+140
-0
lines changed

2 files changed

+140
-0
lines changed

copier.go

+28
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,13 @@ func copier(toValue interface{}, fromValue interface{}, opt Option) (err error)
215215
return
216216
}
217217

218+
if len(converters) > 0 {
219+
if ok, e := set(to, from, opt.DeepCopy, converters); e == nil && ok {
220+
// converter supported
221+
return
222+
}
223+
}
224+
218225
if from.Kind() == reflect.Slice || to.Kind() == reflect.Slice {
219226
isSlice = true
220227
if from.Kind() == reflect.Slice {
@@ -239,6 +246,27 @@ func copier(toValue interface{}, fromValue interface{}, opt Option) (err error)
239246
dest = indirect(to)
240247
}
241248

249+
if len(converters) > 0 {
250+
if ok, e := set(dest, source, opt.DeepCopy, converters); e == nil && ok {
251+
if isSlice {
252+
// FIXME: maybe should check the other types?
253+
if to.Type().Elem().Kind() == reflect.Ptr {
254+
to.Index(i).Set(dest.Addr())
255+
} else {
256+
if to.Len() < i+1 {
257+
reflect.Append(to, dest)
258+
} else {
259+
to.Index(i).Set(dest)
260+
}
261+
}
262+
} else {
263+
to.Set(dest)
264+
}
265+
266+
continue
267+
}
268+
}
269+
242270
destKind := dest.Kind()
243271
initDest := false
244272
if destKind == reflect.Interface {

copier_issue170_test.go

+112
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
package copier_test
2+
3+
import (
4+
"github.com/jinzhu/copier"
5+
"reflect"
6+
"testing"
7+
)
8+
9+
type A struct {
10+
A int
11+
}
12+
type B struct {
13+
A int
14+
b int
15+
}
16+
17+
var copied = B{A: 2387483274, b: 128387134}
18+
19+
func newOptWithConverter() copier.Option {
20+
return copier.Option{
21+
Converters: []copier.TypeConverter{
22+
{
23+
SrcType: A{},
24+
DstType: B{},
25+
Fn: func(from interface{}) (interface{}, error) {
26+
return copied, nil
27+
},
28+
},
29+
},
30+
}
31+
}
32+
33+
func Test_Struct_With_Converter(t *testing.T) {
34+
aa := A{A: 11}
35+
bb := B{A: 10, b: 100}
36+
err := copier.CopyWithOption(&bb, &aa, newOptWithConverter())
37+
if err != nil || !reflect.DeepEqual(copied, bb) {
38+
t.Fatalf("Got %v, wanted %v", bb, copied)
39+
}
40+
}
41+
42+
func Test_Map_With_Converter(t *testing.T) {
43+
aa := map[string]*A{
44+
"a": &A{A: 10},
45+
}
46+
47+
bb := map[string]*B{
48+
"a": &B{A: 10, b: 100},
49+
}
50+
51+
err := copier.CopyWithOption(&bb, &aa, newOptWithConverter())
52+
if err != nil {
53+
t.Fatalf("copy with converter failed: %v", err)
54+
}
55+
56+
for _, v := range bb {
57+
wanted := &copied
58+
if !reflect.DeepEqual(v, wanted) {
59+
t.Fatalf("Got %v, wanted %v", v, wanted)
60+
}
61+
}
62+
}
63+
64+
func Test_Slice_With_Converter(t *testing.T) {
65+
aa := []*A{
66+
&A{A: 10},
67+
}
68+
69+
bb := []*B{
70+
&B{A: 10, b: 100},
71+
}
72+
73+
err := copier.CopyWithOption(&bb, &aa, newOptWithConverter())
74+
75+
if err != nil {
76+
t.Fatalf("copy slice error: %v", err)
77+
}
78+
79+
wanted := copied
80+
for _, v := range bb {
81+
temp := v
82+
if !reflect.DeepEqual(*temp, wanted) {
83+
t.Fatalf("Got %v, wanted %v", *temp, wanted)
84+
}
85+
}
86+
}
87+
88+
func Test_Slice_Embedded_With_Converter(t *testing.T) {
89+
aa := struct {
90+
A []*A
91+
}{
92+
A: []*A{&A{A: 10}},
93+
}
94+
95+
bb := struct {
96+
A []*B
97+
}{
98+
A: []*B{&B{A: 10, b: 100}},
99+
}
100+
101+
err := copier.CopyWithOption(&bb, &aa, newOptWithConverter())
102+
103+
wanted := struct {
104+
A []*B
105+
}{
106+
A: []*B{&copied},
107+
}
108+
109+
if err != nil || !reflect.DeepEqual(bb, wanted) {
110+
t.Fatalf("Got %v, wanted %v", bb, wanted)
111+
}
112+
}

0 commit comments

Comments
 (0)