aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2013-10-17 12:13:33 -0400
committerRuss Cox <rsc@golang.org>2013-10-17 12:13:33 -0400
commit4dce7f85751e42fd1149fa46938edb8a046d4c3a (patch)
treee3264ec23644a7f71a405bed3a658607d973c67d
parente39eda1366384cdef21f04c5c964ae93e2ea9ce3 (diff)
downloadgo-4dce7f85751e42fd1149fa46938edb8a046d4c3a.tar.gz
go-4dce7f85751e42fd1149fa46938edb8a046d4c3a.zip
encoding/xml: accept chains of interfaces and pointers
Fixes #6556. R=golang-dev, iant, adg CC=golang-dev https://golang.org/cl/14747043
-rw-r--r--src/pkg/encoding/xml/marshal.go13
-rw-r--r--src/pkg/encoding/xml/marshal_test.go36
2 files changed, 43 insertions, 6 deletions
diff --git a/src/pkg/encoding/xml/marshal.go b/src/pkg/encoding/xml/marshal.go
index e723a193cf..d9522e0b39 100644
--- a/src/pkg/encoding/xml/marshal.go
+++ b/src/pkg/encoding/xml/marshal.go
@@ -354,18 +354,19 @@ func (p *printer) marshalValue(val reflect.Value, finfo *fieldInfo, startTemplat
return nil
}
- kind := val.Kind()
- typ := val.Type()
-
- // Drill into pointers/interfaces
- if kind == reflect.Ptr || kind == reflect.Interface {
+ // Drill into interfaces and pointers.
+ // This can turn into an infinite loop given a cyclic chain,
+ // but it matches the Go 1 behavior.
+ for val.Kind() == reflect.Interface || val.Kind() == reflect.Ptr {
if val.IsNil() {
return nil
}
val = val.Elem()
- typ = val.Type()
}
+ kind := val.Kind()
+ typ := val.Type()
+
// Check for marshaler.
if val.CanInterface() && typ.Implements(marshalerType) {
return p.marshalInterface(val.Interface().(Marshaler), defaultStart(typ, finfo, startTemplate))
diff --git a/src/pkg/encoding/xml/marshal_test.go b/src/pkg/encoding/xml/marshal_test.go
index 1444c9cc2f..d34118a3d8 100644
--- a/src/pkg/encoding/xml/marshal_test.go
+++ b/src/pkg/encoding/xml/marshal_test.go
@@ -314,6 +314,10 @@ type MarshalerStruct struct {
Foo MyMarshalerAttrTest `xml:",attr"`
}
+func ifaceptr(x interface{}) interface{} {
+ return &x
+}
+
var (
nameAttr = "Sarah"
ageAttr = uint(12)
@@ -356,6 +360,7 @@ var marshalTests = []struct {
{Value: &Plain{NamedType("potato")}, ExpectXML: `<Plain><V>potato</V></Plain>`},
{Value: &Plain{[]int{1, 2, 3}}, ExpectXML: `<Plain><V>1</V><V>2</V><V>3</V></Plain>`},
{Value: &Plain{[3]int{1, 2, 3}}, ExpectXML: `<Plain><V>1</V><V>2</V><V>3</V></Plain>`},
+ {Value: ifaceptr(true), MarshalOnly: true, ExpectXML: `<bool>true</bool>`},
// Test time.
{
@@ -1113,3 +1118,34 @@ func BenchmarkUnmarshal(b *testing.B) {
Unmarshal(xml, &Feed{})
}
}
+
+// golang.org/issue/6556
+func TestStructPointerMarshal(t *testing.T) {
+ type A struct {
+ XMLName string `xml:"a"`
+ B []interface{}
+ }
+ type C struct {
+ XMLName Name
+ Value string `xml:"value"`
+ }
+
+ a := new(A)
+ a.B = append(a.B, &C{
+ XMLName: Name{Local: "c"},
+ Value: "x",
+ })
+
+ b, err := Marshal(a)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if x := string(b); x != "<a><c><value>x</value></c></a>" {
+ t.Fatal(x)
+ }
+ var v A
+ err = Unmarshal(b, &v)
+ if err != nil {
+ t.Fatal(err)
+ }
+}