Skip to content

Commit e0c0b8d

Browse files
committed
valueIsScalar improvements
1 parent fb1c87b commit e0c0b8d

File tree

2 files changed

+46
-9
lines changed

2 files changed

+46
-9
lines changed

diff/diff.go

+16-9
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,8 @@ func Diff(lhs, rhs interface{}, opts ...ConfigOpt) (Differ, error) {
4343
}
4444

4545
func diff(c config, lhs, rhs interface{}, visited *visited) (Differ, error) {
46-
lhsVal := reflect.ValueOf(lhs)
47-
rhsVal := reflect.ValueOf(rhs)
46+
lhsVal, lhs := indirectValueOf(lhs)
47+
rhsVal, rhs := indirectValueOf(rhs)
4848

4949
if d, ok := nilCheck(lhs, rhs); ok {
5050
return d, nil
@@ -56,7 +56,7 @@ func diff(c config, lhs, rhs interface{}, visited *visited) (Differ, error) {
5656
return types{lhs, rhs}, ErrCyclic
5757
}
5858

59-
if valuesAreScalar(lhsVal, rhsVal) {
59+
if valueIsScalar(lhsVal) && valueIsScalar(rhsVal) {
6060
return scalar{lhs, rhs}, nil
6161
}
6262
if lhsVal.Kind() != rhsVal.Kind() {
@@ -75,15 +75,22 @@ func diff(c config, lhs, rhs interface{}, visited *visited) (Differ, error) {
7575
return types{lhs, rhs}, &ErrUnsupported{lhsVal.Type(), rhsVal.Type()}
7676
}
7777

78-
func valuesAreScalar(lhs, rhs reflect.Value) bool {
79-
if lhs.Kind() == reflect.Struct || rhs.Kind() == reflect.Struct {
80-
return false
78+
func indirectValueOf(i interface{}) (reflect.Value, interface{}) {
79+
v := reflect.Indirect(reflect.ValueOf(i))
80+
if !v.IsValid() || !v.CanInterface() {
81+
return reflect.ValueOf(i), i
8182
}
82-
if lhs.Kind() == reflect.Array || rhs.Kind() == reflect.Array {
83+
84+
return v, v.Interface()
85+
}
86+
87+
func valueIsScalar(v reflect.Value) bool {
88+
switch v.Kind() {
89+
default:
90+
return v.Type().Comparable()
91+
case reflect.Struct, reflect.Array, reflect.Ptr, reflect.Chan:
8392
return false
8493
}
85-
86-
return lhs.Type().Comparable() && rhs.Type().Comparable()
8794
}
8895

8996
func nilCheck(lhs, rhs interface{}) (Differ, bool) {

diff/diff_test.go

+30
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package diff
22

33
import (
44
"fmt"
5+
"reflect"
56
"strings"
67
"testing"
78
)
@@ -1128,3 +1129,32 @@ func TestIsSlice(t *testing.T) {
11281129
t.Error("IsSlice(Diff(map{...}, map{...})) = false, expected true")
11291130
}
11301131
}
1132+
1133+
func TestValueIsScalar(t *testing.T) {
1134+
for _, test := range []struct {
1135+
In interface{}
1136+
Expected bool
1137+
}{
1138+
{int(42), true},
1139+
{int8(23), true},
1140+
{"foo", true},
1141+
{true, true},
1142+
{float32(1.2), true},
1143+
{complex(5, -3), true},
1144+
1145+
{[]byte("foo"), false},
1146+
{struct{}{}, false},
1147+
{&struct{}{}, false},
1148+
{[]int{1, 2, 3}, false},
1149+
{[3]int{1, 2, 3}, false},
1150+
{map[string]int{"foo": 22}, false},
1151+
{func() {}, false},
1152+
{make(chan struct{}), false},
1153+
} {
1154+
v := reflect.ValueOf(test.In)
1155+
got := valueIsScalar(v)
1156+
if got != test.Expected {
1157+
t.Errorf("valueIsScalar(%T) = %v, expected %v", test.In, got, test.Expected)
1158+
}
1159+
}
1160+
}

0 commit comments

Comments
 (0)