]> Cypherpunks repositories - gostls13.git/commitdiff
fmt: improve go syntax handling of byte-derived arrays and slices
authorRobert Daniel Kortschak <dan.kortschak@adelaide.edu.au>
Thu, 31 Jan 2013 01:53:53 +0000 (17:53 -0800)
committerRuss Cox <rsc@golang.org>
Thu, 31 Jan 2013 01:53:53 +0000 (17:53 -0800)
Fixes #4685.

R=golang-dev, adg, remyoudompheng, rsc
CC=golang-dev
https://golang.org/cl/7205047

src/pkg/fmt/fmt_test.go
src/pkg/fmt/print.go

index 66d1aa11adaf350a3bc7cec633055bbb8e6d3794..4158c6c353a110901d47f59dc9cbd4209f035db6 100644 (file)
@@ -105,6 +105,9 @@ func (p *P) String() string {
        return "String(p)"
 }
 
+var barray = [5]renamedUint8{1, 2, 3, 4, 5}
+var bslice = barray[:]
+
 var b byte
 
 var fmttests = []struct {
@@ -332,14 +335,18 @@ var fmttests = []struct {
        // arrays
        {"%v", array, "[1 2 3 4 5]"},
        {"%v", iarray, "[1 hello 2.5 <nil>]"},
+       {"%v", barray, "[1 2 3 4 5]"},
        {"%v", &array, "&[1 2 3 4 5]"},
        {"%v", &iarray, "&[1 hello 2.5 <nil>]"},
+       {"%v", &barray, "&[1 2 3 4 5]"},
 
        // slices
        {"%v", slice, "[1 2 3 4 5]"},
        {"%v", islice, "[1 hello 2.5 <nil>]"},
+       {"%v", bslice, "[1 2 3 4 5]"},
        {"%v", &slice, "&[1 2 3 4 5]"},
        {"%v", &islice, "&[1 hello 2.5 <nil>]"},
+       {"%v", &bslice, "&[1 2 3 4 5]"},
 
        // complexes with %v
        {"%v", 1 + 2i, "(1+2i)"},
@@ -382,6 +389,8 @@ var fmttests = []struct {
        {"%#v", map[int]byte(nil), `map[int]uint8(nil)`},
        {"%#v", map[int]byte{}, `map[int]uint8{}`},
        {"%#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
        {"%#x", []int{1, 2, 15}, `[0x1 0x2 0xf]`},
@@ -407,6 +416,9 @@ var fmttests = []struct {
        {"%x", renamedString("thing"), "7468696e67"},
        {"%d", renamedBytes([]byte{1, 2, 15}), `[1 2 15]`},
        {"%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", renamedFloat64(33), "33"},
        {"%v", renamedComplex64(3 + 4i), "(3+4i)"},
index 4078f4a910b9fbd679b1b7031f55192091779bc5..636bb5e1a1a8a19cfeff541774a688b39769ca02 100644 (file)
@@ -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 goSyntax {
-                       p.buf.Write(bytesBytes)
+                       if typ == nil {
+                               p.buf.Write(bytesBytes)
+                       } else {
+                               p.buf.WriteString(typ.String())
+                               p.buf.WriteByte('{')
+                       }
                } else {
                        p.buf.WriteByte('[')
                }
@@ -793,7 +798,7 @@ func (p *pp) printField(field interface{}, verb rune, plus, goSyntax bool, depth
                p.fmtString(f, verb, goSyntax)
                wasString = verb == 's' || verb == 'v'
        case []byte:
-               p.fmtBytes(f, verb, goSyntax, depth)
+               p.fmtBytes(f, verb, goSyntax, nil, depth)
                wasString = verb == 's'
        default:
                // Restore flags in case handleMethods finds a Formatter.
@@ -939,19 +944,22 @@ BigSwitch:
                }
        case reflect.Array, reflect.Slice:
                // Byte slices are special.
-               if f.Type().Elem().Kind() == reflect.Uint8 {
-                       // We know it's a slice of bytes, but we also know it does not have static type
-                       // []byte, or it would have been caught above.  Therefore we cannot convert
-                       // it directly in the (slightly) obvious way: f.Interface().([]byte); it doesn't have
-                       // that type, and we can't write an expression of the right type and do a
-                       // conversion because we don't have a static way to write the right type.
-                       // So we build a slice by hand.  This is a rare case but it would be nice
-                       // if reflection could help a little more.
-                       bytes := make([]byte, f.Len())
-                       for i := range bytes {
-                               bytes[i] = byte(f.Index(i).Uint())
+               if typ := f.Type(); typ.Elem().Kind() == reflect.Uint8 {
+                       var bytes []byte
+                       if f.Kind() == reflect.Slice {
+                               bytes = f.Bytes()
+                       } else if f.CanAddr() {
+                               bytes = f.Slice(0, f.Len()).Bytes()
+                       } 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.
+                               bytes = make([]byte, f.Len())
+                               for i := range bytes {
+                                       bytes[i] = byte(f.Index(i).Uint())
+                               }
                        }
-                       p.fmtBytes(bytes, verb, goSyntax, depth)
+                       p.fmtBytes(bytes, verb, goSyntax, typ, depth)
                        wasString = verb == 's'
                        break
                }