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

rm panic on config.SortKeys with an unexported map with array key #111

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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 25 additions & 13 deletions spew/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ func newValuesSorter(values []reflect.Value, cs *ConfigState) sort.Interface {
// directly, or whether it should be considered for sorting by surrogate keys
// (if the ConfigState allows it).
func canSortSimply(kind reflect.Kind) bool {
// This switch parallels valueSortLess, except for the default case.
// This switch parallels valueLessEqual, except for the default case.
switch kind {
case reflect.Bool:
return true
Expand Down Expand Up @@ -289,43 +289,55 @@ func (s *valuesSorter) Swap(i, j int) {
}
}

// valueSortLess returns whether the first value should sort before the second
// valueLessEqual returns whether the first value should sort before the second
// value. It is used by valueSorter.Less as part of the sort.Interface
// implementation.
func valueSortLess(a, b reflect.Value) bool {
func valueLessEqual(a, b reflect.Value) (less, equal bool) {
switch a.Kind() {
case reflect.Bool:
return !a.Bool() && b.Bool()
av, bv := a.Bool(), b.Bool()
return !av && bv, av == bv
case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int:
return a.Int() < b.Int()
av, bv := a.Int(), b.Int()
return av < bv, av == bv
case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint:
return a.Uint() < b.Uint()
av, bv := a.Uint(), b.Uint()
return av < bv, av == bv
case reflect.Float32, reflect.Float64:
return a.Float() < b.Float()
av, bv := a.Float(), b.Float()
return av < bv, av == bv
case reflect.String:
return a.String() < b.String()
av, bv := a.String(), b.String()
return av < bv, av == bv
case reflect.Uintptr:
return a.Uint() < b.Uint()
av, bv := a.Uint(), b.Uint()
return av < bv, av == bv
case reflect.Array:
// Compare the contents of both arrays.
l := a.Len()
for i := 0; i < l; i++ {
av := a.Index(i)
bv := b.Index(i)
if av.Interface() == bv.Interface() {

less, equal := valueLessEqual(av, bv)
if equal {
continue
}
return valueSortLess(av, bv)

return less, false
}
}
return a.String() < b.String()

av, bv := a.String(), b.String()
return av < bv, av == bv
}

// Less returns whether the value at index i should sort before the
// value at index j. It is part of the sort.Interface implementation.
func (s *valuesSorter) Less(i, j int) bool {
if s.strings == nil {
return valueSortLess(s.values[i], s.values[j])
less, _ := valueLessEqual(s.values[i], s.values[j])
return less
}
return s.strings[i] < s.strings[j]
}
Expand Down
30 changes: 30 additions & 0 deletions spew/dump_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1039,4 +1039,34 @@ func TestDumpSortedKeys(t *testing.T) {
t.Errorf("Sorted keys mismatch:\n %v %v", s, expected)
}

type structWithUnexportedMapWithArrayKey struct {
f map[[3]byte]int
}
s = cfg.Sdump(structWithUnexportedMapWithArrayKey{
map[[3]byte]int{
[3]byte{0x1, 0x2, 0x3}: 2,
[3]byte{0x1, 0x3, 0x2}: 3,
[3]byte{0x1, 0x2, 0x2}: 1,
},
})
expected =
`(spew_test.structWithUnexportedMapWithArrayKey) {
f: (map[[3]uint8]int) (len=3) {
([3]uint8) (len=3 cap=3) {
00000000 01 02 02 |...|
}: (int) 1,
([3]uint8) (len=3 cap=3) {
00000000 01 02 03 |...|
}: (int) 2,
([3]uint8) (len=3 cap=3) {
00000000 01 03 02 |...|
}: (int) 3
}
}
`

if s != expected {
t.Errorf("Sorted keys mismatch:\n %v %v", s, expected)
}

}