Format units in decimal except bytes (#199)
In general, decimal formatting is preferred except for []byte
where hexadecimal is preferred for individual elements.
Fixes #185
diff --git a/cmp/report_compare.go b/cmp/report_compare.go
index 17a05ee..d3fa154 100644
--- a/cmp/report_compare.go
+++ b/cmp/report_compare.go
@@ -81,14 +81,19 @@
return opts.FormatDiffSlice(v)
}
+ var withinSlice bool
+ if v.parent != nil && (v.parent.Type.Kind() == reflect.Slice || v.parent.Type.Kind() == reflect.Array) {
+ withinSlice = true
+ }
+
// For leaf nodes, format the value based on the reflect.Values alone.
if v.MaxDepth == 0 {
switch opts.DiffMode {
case diffUnknown, diffIdentical:
// Format Equal.
if v.NumDiff == 0 {
- outx := opts.FormatValue(v.ValueX, visitedPointers{})
- outy := opts.FormatValue(v.ValueY, visitedPointers{})
+ outx := opts.FormatValue(v.ValueX, withinSlice, visitedPointers{})
+ outy := opts.FormatValue(v.ValueY, withinSlice, visitedPointers{})
if v.NumIgnored > 0 && v.NumSame == 0 {
return textEllipsis
} else if outx.Len() < outy.Len() {
@@ -101,8 +106,8 @@
// Format unequal.
assert(opts.DiffMode == diffUnknown)
var list textList
- outx := opts.WithTypeMode(elideType).FormatValue(v.ValueX, visitedPointers{})
- outy := opts.WithTypeMode(elideType).FormatValue(v.ValueY, visitedPointers{})
+ outx := opts.WithTypeMode(elideType).FormatValue(v.ValueX, withinSlice, visitedPointers{})
+ outy := opts.WithTypeMode(elideType).FormatValue(v.ValueY, withinSlice, visitedPointers{})
if outx != nil {
list = append(list, textRecord{Diff: '-', Value: outx})
}
@@ -111,9 +116,9 @@
}
return opts.WithTypeMode(emitType).FormatType(v.Type, list)
case diffRemoved:
- return opts.FormatValue(v.ValueX, visitedPointers{})
+ return opts.FormatValue(v.ValueX, withinSlice, visitedPointers{})
case diffInserted:
- return opts.FormatValue(v.ValueY, visitedPointers{})
+ return opts.FormatValue(v.ValueY, withinSlice, visitedPointers{})
default:
panic("invalid diff mode")
}
diff --git a/cmp/report_reflect.go b/cmp/report_reflect.go
index 2761b62..8f10883 100644
--- a/cmp/report_reflect.go
+++ b/cmp/report_reflect.go
@@ -74,7 +74,7 @@
// FormatValue prints the reflect.Value, taking extra care to avoid descending
// into pointers already in m. As pointers are visited, m is also updated.
-func (opts formatOptions) FormatValue(v reflect.Value, m visitedPointers) (out textNode) {
+func (opts formatOptions) FormatValue(v reflect.Value, withinSlice bool, m visitedPointers) (out textNode) {
if !v.IsValid() {
return nil
}
@@ -108,12 +108,15 @@
return textLine(fmt.Sprint(v.Bool()))
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return textLine(fmt.Sprint(v.Int()))
- case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
- // Unnamed uints are usually bytes or words, so use hexadecimal.
- if t.PkgPath() == "" || t.Kind() == reflect.Uintptr {
+ case reflect.Uint, reflect.Uint16, reflect.Uint32, reflect.Uint64:
+ return textLine(fmt.Sprint(v.Uint()))
+ case reflect.Uint8:
+ if withinSlice {
return textLine(formatHex(v.Uint()))
}
return textLine(fmt.Sprint(v.Uint()))
+ case reflect.Uintptr:
+ return textLine(formatHex(v.Uint()))
case reflect.Float32, reflect.Float64:
return textLine(fmt.Sprint(v.Float()))
case reflect.Complex64, reflect.Complex128:
@@ -129,7 +132,7 @@
if value.IsZero(vv) {
continue // Elide fields with zero values
}
- s := opts.WithTypeMode(autoType).FormatValue(vv, m)
+ s := opts.WithTypeMode(autoType).FormatValue(vv, false, m)
list = append(list, textRecord{Key: t.Field(i).Name, Value: s})
}
return textWrap{"{", list, "}"}
@@ -156,7 +159,7 @@
continue
}
}
- s := opts.WithTypeMode(elideType).FormatValue(vi, m)
+ s := opts.WithTypeMode(elideType).FormatValue(vi, true, m)
list = append(list, textRecord{Value: s})
}
return textWrap{ptr + "{", list, "}"}
@@ -171,7 +174,7 @@
var list textList
for _, k := range value.SortKeys(v.MapKeys()) {
sk := formatMapKey(k)
- sv := opts.WithTypeMode(elideType).FormatValue(v.MapIndex(k), m)
+ sv := opts.WithTypeMode(elideType).FormatValue(v.MapIndex(k), false, m)
list = append(list, textRecord{Key: sk, Value: sv})
}
if opts.PrintAddresses {
@@ -189,7 +192,7 @@
ptr = formatPointer(v)
}
skipType = true // Let the underlying value print the type instead
- return textWrap{"&" + ptr, opts.FormatValue(v.Elem(), m), ""}
+ return textWrap{"&" + ptr, opts.FormatValue(v.Elem(), false, m), ""}
case reflect.Interface:
if v.IsNil() {
return textNil
@@ -197,7 +200,7 @@
// Interfaces accept different concrete types,
// so configure the underlying value to explicitly print the type.
skipType = true // Print the concrete type instead
- return opts.WithTypeMode(emitType).FormatValue(v.Elem(), m)
+ return opts.WithTypeMode(emitType).FormatValue(v.Elem(), false, m)
default:
panic(fmt.Sprintf("%v kind not handled", v.Kind()))
}
@@ -209,7 +212,7 @@
var opts formatOptions
opts.TypeMode = elideType
opts.ShallowPointers = true
- s := opts.FormatValue(v, visitedPointers{}).String()
+ s := opts.FormatValue(v, false, visitedPointers{}).String()
return strings.TrimSpace(s)
}
diff --git a/cmp/report_slices.go b/cmp/report_slices.go
index eafcf2e..6f0847e 100644
--- a/cmp/report_slices.go
+++ b/cmp/report_slices.go
@@ -172,7 +172,9 @@
switch t.Elem().Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
ss = append(ss, fmt.Sprint(v.Index(i).Int()))
- case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+ case reflect.Uint, reflect.Uint16, reflect.Uint32, reflect.Uint64:
+ ss = append(ss, fmt.Sprint(v.Index(i).Uint()))
+ case reflect.Uint8, reflect.Uintptr:
ss = append(ss, formatHex(v.Index(i).Uint()))
case reflect.Bool, reflect.Float32, reflect.Float64, reflect.Complex64, reflect.Complex128:
ss = append(ss, fmt.Sprint(v.Index(i).Interface()))
diff --git a/cmp/testdata/diffs b/cmp/testdata/diffs
index 5471f81..533edf6 100644
--- a/cmp/testdata/diffs
+++ b/cmp/testdata/diffs
@@ -54,8 +54,8 @@
... // 4 identical fields
Size: 1,
ModTime: s"2009-11-10 23:00:00 +0000 UTC",
-- Typeflag: 0x30,
-+ Typeflag: 0x00,
+- Typeflag: 48,
++ Typeflag: 0,
Linkname: "",
Uname: "user",
... // 6 identical fields
@@ -64,8 +64,8 @@
... // 4 identical fields
Size: 2,
ModTime: s"2009-11-11 00:00:00 +0000 UTC",
-- Typeflag: 0x30,
-+ Typeflag: 0x00,
+- Typeflag: 48,
++ Typeflag: 0,
Linkname: "",
Uname: "user",
... // 6 identical fields
@@ -74,8 +74,8 @@
... // 4 identical fields
Size: 4,
ModTime: s"2009-11-11 01:00:00 +0000 UTC",
-- Typeflag: 0x30,
-+ Typeflag: 0x00,
+- Typeflag: 48,
++ Typeflag: 0,
Linkname: "",
Uname: "user",
... // 6 identical fields
@@ -84,8 +84,8 @@
... // 4 identical fields
Size: 8,
ModTime: s"2009-11-11 02:00:00 +0000 UTC",
-- Typeflag: 0x30,
-+ Typeflag: 0x00,
+- Typeflag: 48,
++ Typeflag: 0,
Linkname: "",
Uname: "user",
... // 6 identical fields
@@ -94,8 +94,8 @@
... // 4 identical fields
Size: 16,
ModTime: s"2009-11-11 03:00:00 +0000 UTC",
-- Typeflag: 0x30,
-+ Typeflag: 0x00,
+- Typeflag: 48,
++ Typeflag: 0,
Linkname: "",
Uname: "user",
... // 6 identical fields
@@ -188,8 +188,8 @@
>>> TestDiff/Comparer#46
<<< TestDiff/Transformer
uint8(Inverse(λ, uint16(Inverse(λ, uint32(Inverse(λ, uint64(
-- 0x00,
-+ 0x01,
+- 0,
++ 1,
)))))))
>>> TestDiff/Transformer
<<< TestDiff/Transformer#02
@@ -323,8 +323,8 @@
+ -9, -8, -7,
},
UintsA: []uint16{
-- 0x03e8, 0x07d0, 0x0bb8,
-+ 0x0bb8, 0x07d0, 0x03e8,
+- 1000, 2000, 3000,
++ 3000, 2000, 1000,
},
UintsB: []cmp_test.MyUint{
- 4000, 5000, 6000,
@@ -1029,7 +1029,7 @@
Slaps: []teststructs.Slap{
{
... // 6 identical fields
- Homeland: 0x00,
+ Homeland: 0,
FunnyPrank: "",
Immutable: &teststructs.SlapImmutable{
ID: "immutableSlap",
@@ -1130,7 +1130,7 @@
<<< TestDiff/Project4#03
teststructs.Cartel{
Headquarter: teststructs.Headquarter{
- id: 0x05,
+ id: 5,
location: "moon",
subDivisions: []string{
- "alpha",