Commit 92bc8969 authored by Robert Daniel Kortschak's avatar Robert Daniel Kortschak Committed by Russ Cox

fmt: improve go syntax handling of byte-derived arrays and slices

Fixes #4685.

R=golang-dev, adg, remyoudompheng, rsc
CC=golang-dev
https://golang.org/cl/7205047
parent eea0f199
...@@ -105,6 +105,9 @@ func (p *P) String() string { ...@@ -105,6 +105,9 @@ func (p *P) String() string {
return "String(p)" return "String(p)"
} }
var barray = [5]renamedUint8{1, 2, 3, 4, 5}
var bslice = barray[:]
var b byte var b byte
var fmttests = []struct { var fmttests = []struct {
...@@ -332,14 +335,18 @@ var fmttests = []struct { ...@@ -332,14 +335,18 @@ var fmttests = []struct {
// arrays // arrays
{"%v", array, "[1 2 3 4 5]"}, {"%v", array, "[1 2 3 4 5]"},
{"%v", iarray, "[1 hello 2.5 <nil>]"}, {"%v", iarray, "[1 hello 2.5 <nil>]"},
{"%v", barray, "[1 2 3 4 5]"},
{"%v", &array, "&[1 2 3 4 5]"}, {"%v", &array, "&[1 2 3 4 5]"},
{"%v", &iarray, "&[1 hello 2.5 <nil>]"}, {"%v", &iarray, "&[1 hello 2.5 <nil>]"},
{"%v", &barray, "&[1 2 3 4 5]"},
// slices // slices
{"%v", slice, "[1 2 3 4 5]"}, {"%v", slice, "[1 2 3 4 5]"},
{"%v", islice, "[1 hello 2.5 <nil>]"}, {"%v", islice, "[1 hello 2.5 <nil>]"},
{"%v", bslice, "[1 2 3 4 5]"},
{"%v", &slice, "&[1 2 3 4 5]"}, {"%v", &slice, "&[1 2 3 4 5]"},
{"%v", &islice, "&[1 hello 2.5 <nil>]"}, {"%v", &islice, "&[1 hello 2.5 <nil>]"},
{"%v", &bslice, "&[1 2 3 4 5]"},
// complexes with %v // complexes with %v
{"%v", 1 + 2i, "(1+2i)"}, {"%v", 1 + 2i, "(1+2i)"},
...@@ -382,6 +389,8 @@ var fmttests = []struct { ...@@ -382,6 +389,8 @@ var fmttests = []struct {
{"%#v", map[int]byte(nil), `map[int]uint8(nil)`}, {"%#v", map[int]byte(nil), `map[int]uint8(nil)`},
{"%#v", map[int]byte{}, `map[int]uint8{}`}, {"%#v", map[int]byte{}, `map[int]uint8{}`},
{"%#v", "foo", `"foo"`}, {"%#v", "foo", `"foo"`},
{"%#v", barray, `[5]fmt_test.renamedUint8{0x1, 0x2, 0x3, 0x4, 0x5}`},
{"%#v", bslice, `[]fmt_test.renamedUint8{0x1, 0x2, 0x3, 0x4, 0x5}`},
// slices with other formats // slices with other formats
{"%#x", []int{1, 2, 15}, `[0x1 0x2 0xf]`}, {"%#x", []int{1, 2, 15}, `[0x1 0x2 0xf]`},
...@@ -407,6 +416,9 @@ var fmttests = []struct { ...@@ -407,6 +416,9 @@ var fmttests = []struct {
{"%x", renamedString("thing"), "7468696e67"}, {"%x", renamedString("thing"), "7468696e67"},
{"%d", renamedBytes([]byte{1, 2, 15}), `[1 2 15]`}, {"%d", renamedBytes([]byte{1, 2, 15}), `[1 2 15]`},
{"%q", renamedBytes([]byte("hello")), `"hello"`}, {"%q", renamedBytes([]byte("hello")), `"hello"`},
{"%x", []renamedUint8{'a', 'b', 'c'}, "616263"},
{"%s", []renamedUint8{'h', 'e', 'l', 'l', 'o'}, "hello"},
{"%q", []renamedUint8{'h', 'e', 'l', 'l', 'o'}, `"hello"`},
{"%v", renamedFloat32(22), "22"}, {"%v", renamedFloat32(22), "22"},
{"%v", renamedFloat64(33), "33"}, {"%v", renamedFloat64(33), "33"},
{"%v", renamedComplex64(3 + 4i), "(3+4i)"}, {"%v", renamedComplex64(3 + 4i), "(3+4i)"},
......
...@@ -545,10 +545,15 @@ func (p *pp) fmtString(v string, verb rune, goSyntax bool) { ...@@ -545,10 +545,15 @@ func (p *pp) fmtString(v string, verb rune, goSyntax bool) {
} }
} }
func (p *pp) fmtBytes(v []byte, verb rune, goSyntax bool, depth int) { func (p *pp) fmtBytes(v []byte, verb rune, goSyntax bool, typ reflect.Type, depth int) {
if verb == 'v' || verb == 'd' { if verb == 'v' || verb == 'd' {
if goSyntax { if goSyntax {
if typ == nil {
p.buf.Write(bytesBytes) p.buf.Write(bytesBytes)
} else {
p.buf.WriteString(typ.String())
p.buf.WriteByte('{')
}
} else { } else {
p.buf.WriteByte('[') p.buf.WriteByte('[')
} }
...@@ -793,7 +798,7 @@ func (p *pp) printField(field interface{}, verb rune, plus, goSyntax bool, depth ...@@ -793,7 +798,7 @@ func (p *pp) printField(field interface{}, verb rune, plus, goSyntax bool, depth
p.fmtString(f, verb, goSyntax) p.fmtString(f, verb, goSyntax)
wasString = verb == 's' || verb == 'v' wasString = verb == 's' || verb == 'v'
case []byte: case []byte:
p.fmtBytes(f, verb, goSyntax, depth) p.fmtBytes(f, verb, goSyntax, nil, depth)
wasString = verb == 's' wasString = verb == 's'
default: default:
// Restore flags in case handleMethods finds a Formatter. // Restore flags in case handleMethods finds a Formatter.
...@@ -939,19 +944,22 @@ BigSwitch: ...@@ -939,19 +944,22 @@ BigSwitch:
} }
case reflect.Array, reflect.Slice: case reflect.Array, reflect.Slice:
// Byte slices are special. // Byte slices are special.
if f.Type().Elem().Kind() == reflect.Uint8 { if typ := f.Type(); typ.Elem().Kind() == reflect.Uint8 {
// We know it's a slice of bytes, but we also know it does not have static type var bytes []byte
// []byte, or it would have been caught above. Therefore we cannot convert if f.Kind() == reflect.Slice {
// it directly in the (slightly) obvious way: f.Interface().([]byte); it doesn't have bytes = f.Bytes()
// that type, and we can't write an expression of the right type and do a } else if f.CanAddr() {
// conversion because we don't have a static way to write the right type. bytes = f.Slice(0, f.Len()).Bytes()
// So we build a slice by hand. This is a rare case but it would be nice } else {
// We have an array, but we cannot Slice() a non-addressable array,
// so we build a slice by hand. This is a rare case but it would be nice
// if reflection could help a little more. // if reflection could help a little more.
bytes := make([]byte, f.Len()) bytes = make([]byte, f.Len())
for i := range bytes { for i := range bytes {
bytes[i] = byte(f.Index(i).Uint()) bytes[i] = byte(f.Index(i).Uint())
} }
p.fmtBytes(bytes, verb, goSyntax, depth) }
p.fmtBytes(bytes, verb, goSyntax, typ, depth)
wasString = verb == 's' wasString = verb == 's'
break break
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment