Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

V2 [WIP] #247

Draft
wants to merge 4 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 6 additions & 0 deletions go.work
@@ -0,0 +1,6 @@
go 1.20

use (
.
./v2
)
4 changes: 2 additions & 2 deletions mergo_test.go
Expand Up @@ -6,7 +6,7 @@
package mergo_test

import (
"io/ioutil"
"os"
"reflect"
"strings"
"testing"
Expand Down Expand Up @@ -846,7 +846,7 @@ func TestNestedPtrValueInMap(t *testing.T) {

func loadYAML(path string) (m map[string]interface{}) {
m = make(map[string]interface{})
raw, _ := ioutil.ReadFile(path)
raw, _ := os.ReadFile(path)
_ = yaml.Unmarshal(raw, &m)
return
}
Expand Down
45 changes: 45 additions & 0 deletions v2/addressables_test.go
@@ -0,0 +1,45 @@
package mergo_test

import (
"testing"

"dario.cat/mergo/v2"
)

func litPtr[T any](v T) *T {
return &v
}

func TestIntMerge(t *testing.T) {
t.Parallel()

testCases := []struct {
dst *int
src int
want *int
}{
{dst: litPtr(0), src: 1, want: litPtr(1)},
{dst: litPtr(2), src: 1, want: litPtr(2)},
{dst: nil, src: 1, want: nil},
{dst: litPtr(3), src: 0, want: litPtr(3)},
}
for _, tc := range testCases {
tc := tc

t.Run("", func(t *testing.T) {
t.Parallel()

mergo.Merge(tc.dst, tc.src)
if tc.dst == nil {
if tc.want != nil {
t.Errorf("expected %v, got %v", *tc.want, tc.dst)
}

return
}
if *tc.dst != *tc.want {
t.Errorf("expected %v, got %v", *tc.want, *tc.dst)
}
})
}
}
5 changes: 5 additions & 0 deletions v2/go.mod
@@ -0,0 +1,5 @@
module dario.cat/mergo/v2

go 1.20

require github.com/google/go-cmp v0.5.9
2 changes: 2 additions & 0 deletions v2/go.sum
@@ -0,0 +1,2 @@
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
28 changes: 28 additions & 0 deletions v2/merge.go
@@ -0,0 +1,28 @@
package mergo

import "reflect"

// Merge (WIP) merges src into dst recursively setting src values on dst
// if src values are not zero values and dst values are zero values.
// Breaking change: src can't be a T pointer anymore.
//
//go:noinline
func Merge[T any](dst *T, src T) {
if dst == nil {
return
}

elm := reflect.ValueOf(*dst)

// If dst is an interface, we need to get the underlying value.
if elm.Kind() == reflect.Interface {
elm = elm.Elem()
}

// If dst is a non-zero value, we don't need to do anything.
if !elm.IsZero() {
return
}

*dst = src
}
46 changes: 46 additions & 0 deletions v2/unadressables_test.go
@@ -0,0 +1,46 @@
package mergo_test

import (
"testing"

"dario.cat/mergo/v2"
"github.com/google/go-cmp/cmp"
)

func ifc[T any](v T) interface{} {
return v
}

func TestInterfaceMerge(t *testing.T) {
t.Parallel()

testCases := []struct {
dst *interface{}
src interface{}
want interface{}
}{
{dst: litPtr(ifc(0)), src: 1, want: 1},
{dst: litPtr(ifc(2)), src: 1, want: 2},
{dst: nil, src: 1, want: nil},
{dst: litPtr(ifc(3)), src: 0, want: 3},
}
for _, tc := range testCases {
tc := tc

t.Run("", func(t *testing.T) {
t.Parallel()

mergo.Merge(tc.dst, tc.src)
if tc.dst == nil {
if tc.want != nil {
t.Errorf("expected %v, got %v", tc.want, tc.dst)
}

return
}
if !cmp.Equal(*tc.dst, tc.want) {
t.Errorf("expected %v, got %v", tc.want, *tc.dst)
}
})
}
}