From a74521df12f09f92f8f99ad93e1f1e76527c27e5 Mon Sep 17 00:00:00 2001 From: Renat Mennanov Date: Thu, 14 Jul 2022 23:51:55 -0700 Subject: [PATCH] Set dst slice to nil when src slice is nil. --- copy.go | 6 +++++ copy_test.go | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+) diff --git a/copy.go b/copy.go index 1f3659e..fdf32d9 100644 --- a/copy.go +++ b/copy.go @@ -169,6 +169,12 @@ func structToStruct(filter FieldFilter, src, dst *reflect.Value, userOptions *op } case reflect.Slice: + if src.IsNil() { + // If the source slice is nil the dst slice is set to nil too. + dst.Set(*src) + break + } + dstLen := dst.Len() srcLen := userOptions.CopyListSize(src) diff --git a/copy_test.go b/copy_test.go index 915d2dc..5a9daeb 100644 --- a/copy_test.go +++ b/copy_test.go @@ -530,6 +530,46 @@ func TestStructToStruct_EntireSlice_NonEmptyDst(t *testing.T) { }, dst) } +func TestStructToStruct_NilSrcSlice_NonEmptyDst(t *testing.T) { + type A struct { + Field1 string + Field2 int + } + type B struct { + Field1 string + A []A + } + src := &B{ + Field1: "src StringerB field1", + A: nil, + } + dst := &B{ + Field1: "dst StringerB field1", + A: []A{ + { + Field1: "dst StringerA field1 0", + Field2: 10, + }, + { + Field1: "dst StringerA field1 1", + Field2: 20, + }, + { + Field1: "dst StringerA field1 2", + Field2: 30, + }, + }, + } + + mask := fieldmask_utils.MaskFromString("Field1,A") + err := fieldmask_utils.StructToStruct(mask, src, dst) + require.NoError(t, err) + assert.Equal(t, &B{ + Field1: src.Field1, + A: src.A, + }, dst) +} + func TestStructToStruct_SliceOfPtrsToStruct_EmptyDst(t *testing.T) { type A struct { Field1 string @@ -1404,6 +1444,36 @@ func TestStructToMap_EntireSlice_NonEmptyDst(t *testing.T) { }, dst) } +func TestStructToMap_NilSrcSlice_NonEmptyDst(t *testing.T) { + type A struct { + Field1 string + Field2 string + } + type B struct { + FieldA []A + } + src := &B{FieldA: nil} + dst := map[string]interface{}{ + "FieldA": []map[string]interface{}{ + { + "Field1": "dst ele1 field1", + }, + { + "Field2": "dst ele2 field 2", + }, + { + "Field1": "dst ele3 field 3", + }, + }, + } + mask := fieldmask_utils.MaskFromString("FieldA") + err := fieldmask_utils.StructToMap(mask, src, dst) + require.NoError(t, err) + assert.Equal(t, map[string]interface{}{ + "FieldA": []map[string]interface{}{}, + }, dst) +} + func TestStructToMap_EntireSlice_DstSliceLenIsLessThanSource(t *testing.T) { type A struct { Field1 string