From 1ab8e48743abd8155bfe0260746aab9813e06ba9 Mon Sep 17 00:00:00 2001 From: Borys Tomala Date: Thu, 28 Apr 2016 17:27:28 +0200 Subject: [PATCH 1/3] Added type checking --- copier.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/copier.go b/copier.go index a308656..09430b4 100644 --- a/copier.go +++ b/copier.go @@ -67,7 +67,7 @@ func Copy(toValue interface{}, fromValue interface{}) (err error) { fromField := source.FieldByName(name) toField := dest.FieldByName(name) toMethod := dest.Addr().MethodByName(name) - if fromField.IsValid() && toField.IsValid() && toField.CanSet() { + if fromField.IsValid() && toField.IsValid() && toField.CanSet() && toField.Type() == fromField.Type() { toField.Set(fromField) } From f4aa2ce3ff00356938c7b35d6dccfffaa2ddbe1a Mon Sep 17 00:00:00 2001 From: Borys Tomala Date: Fri, 29 Apr 2016 09:34:02 +0200 Subject: [PATCH 2/3] Added checking if type is assignable --- copier.go | 11 ++++- copier_test.go | 114 ++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 121 insertions(+), 4 deletions(-) diff --git a/copier.go b/copier.go index 09430b4..e8c5e7e 100644 --- a/copier.go +++ b/copier.go @@ -67,11 +67,18 @@ func Copy(toValue interface{}, fromValue interface{}) (err error) { fromField := source.FieldByName(name) toField := dest.FieldByName(name) toMethod := dest.Addr().MethodByName(name) - if fromField.IsValid() && toField.IsValid() && toField.CanSet() && toField.Type() == fromField.Type() { + + canCopy := fromField.IsValid() && toField.IsValid() && + toField.CanSet() && fromField.Type().AssignableTo(toField.Type()) + + if canCopy { toField.Set(fromField) } - if fromField.IsValid() && toMethod.IsValid() { + canCopy = fromField.IsValid() && toMethod.IsValid() && + fromField.Type().AssignableTo(toMethod.Type().In(0)) + + if canCopy { toMethod.Call([]reflect.Value{fromField}) } } diff --git a/copier_test.go b/copier_test.go index 4f5882c..0927a0a 100644 --- a/copier_test.go +++ b/copier_test.go @@ -41,6 +41,41 @@ type HaveEmbed struct { Base } +type TypeStruct1 struct { + Field1 string + Field2 string +} + +type TypeStruct2 struct { + Field1 int + Field2 string +} + +type TypeStruct3 struct { + Field1 interface{} + Field2 string +} + +type TypeStruct4 struct { + field1 int + Field2 string +} + +type TypeStruct5 struct { + field1 string + Field2 string +} + +func (t *TypeStruct4) Field1(i int) { + t.field1 = i +} + +func (t *TypeStruct5) Field1(i interface{}) { + if v, ok := i.(string); ok { + t.field1 = v + } +} + func (employee *Employee) Role(role string) { employee.SuperRule = "Super " + role } @@ -54,9 +89,84 @@ func TestEmbedded(t *testing.T) { embeded.EmbedField2 = 4 Copy(&base, &embeded) +} + +func TestDifferentType(t *testing.T) { + defer func() { + if r := recover(); r != nil { + t.Errorf("The copy did panic") + } + }() + + ts := &TypeStruct1 { + Field1: "str1", + Field2: "str2", + } + + ts2 := &TypeStruct2 {} + + Copy(ts2, ts) +} + +func TestDifferentTypeMethod(t *testing.T) { + defer func() { + if r := recover(); r != nil { + t.Errorf("The copy did panic") + } + }() + + ts := &TypeStruct1 { + Field1: "str1", + Field2: "str2", + } + + ts4 := &TypeStruct4 {} + + Copy(ts4, ts) +} + +func TestAssignableType(t *testing.T) { + defer func() { + if r := recover(); r != nil { + t.Errorf("The copy did panic") + } + }() + + ts := &TypeStruct1 { + Field1: "str1", + Field2: "str2", + } + + ts3 := &TypeStruct3 {} + + Copy(ts3, ts) + + if v, ok := ts3.Field1.(string); !ok { + t.Error("Assign to interface{} type did not succeed") + } else if v != "str1" { + t.Error("String haven't been copied correctly") + } +} + +func TestAssignableTypeMethod(t *testing.T) { + defer func() { + if r := recover(); r != nil { + t.Errorf("The copy did panic") + } + }() + + ts := &TypeStruct1 { + Field1: "str1", + Field2: "str2", + } + + ts5 := &TypeStruct5 {} + + Copy(ts5, ts) + - if base.BaseField1 != 1 { - t.Error("Embedded fields not copied") + if ts5.field1 != "str1" { + t.Error("String haven't been copied correctly through method") } } From 16fea1e5424e67baea92790819528ff8a90c4cf5 Mon Sep 17 00:00:00 2001 From: Borys Tomala Date: Fri, 29 Apr 2016 09:37:33 +0200 Subject: [PATCH 3/3] fixed accidentally broken test --- copier_test.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/copier_test.go b/copier_test.go index 0927a0a..977194d 100644 --- a/copier_test.go +++ b/copier_test.go @@ -89,6 +89,10 @@ func TestEmbedded(t *testing.T) { embeded.EmbedField2 = 4 Copy(&base, &embeded) + + if base.BaseField1 != 1 { + t.Error("Embedded fields not copied") + } } func TestDifferentType(t *testing.T) {