From 92bc89690988f30863fdafa4a2e353a99edf5ef1 Mon Sep 17 00:00:00 2001 From: Robert Daniel Kortschak Date: Wed, 30 Jan 2013 17:53:53 -0800 Subject: [PATCH] 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 --- src/pkg/fmt/fmt_test.go | 12 ++++++++++++ src/pkg/fmt/print.go | 38 +++++++++++++++++++++++--------------- 2 files changed, 35 insertions(+), 15 deletions(-) diff --git a/src/pkg/fmt/fmt_test.go b/src/pkg/fmt/fmt_test.go index 66d1aa11ad..4158c6c353 100644 --- a/src/pkg/fmt/fmt_test.go +++ b/src/pkg/fmt/fmt_test.go @@ -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 ]"}, + {"%v", barray, "[1 2 3 4 5]"}, {"%v", &array, "&[1 2 3 4 5]"}, {"%v", &iarray, "&[1 hello 2.5 ]"}, + {"%v", &barray, "&[1 2 3 4 5]"}, // slices {"%v", slice, "[1 2 3 4 5]"}, {"%v", islice, "[1 hello 2.5 ]"}, + {"%v", bslice, "[1 2 3 4 5]"}, {"%v", &slice, "&[1 2 3 4 5]"}, {"%v", &islice, "&[1 hello 2.5 ]"}, + {"%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)"}, diff --git a/src/pkg/fmt/print.go b/src/pkg/fmt/print.go index 4078f4a910..636bb5e1a1 100644 --- a/src/pkg/fmt/print.go +++ b/src/pkg/fmt/print.go @@ -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 } -- 2.48.1