aboutsummaryrefslogtreecommitdiff
path: root/src/encoding/xml/marshal.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/encoding/xml/marshal.go')
-rw-r--r--src/encoding/xml/marshal.go127
1 files changed, 71 insertions, 56 deletions
diff --git a/src/encoding/xml/marshal.go b/src/encoding/xml/marshal.go
index 133503fa2d..13fbeeeedc 100644
--- a/src/encoding/xml/marshal.go
+++ b/src/encoding/xml/marshal.go
@@ -416,12 +416,6 @@ func (p *printer) popPrefix() {
}
}
-var (
- marshalerType = reflect.TypeFor[Marshaler]()
- marshalerAttrType = reflect.TypeFor[MarshalerAttr]()
- textMarshalerType = reflect.TypeFor[encoding.TextMarshaler]()
-)
-
// marshalValue writes one or more XML elements representing val.
// If val was obtained from a struct field, finfo must have its details.
func (p *printer) marshalValue(val reflect.Value, finfo *fieldInfo, startTemplate *StartElement) error {
@@ -450,24 +444,32 @@ func (p *printer) marshalValue(val reflect.Value, finfo *fieldInfo, startTemplat
typ := val.Type()
// Check for marshaler.
- if val.CanInterface() && typ.Implements(marshalerType) {
- return p.marshalInterface(val.Interface().(Marshaler), defaultStart(typ, finfo, startTemplate))
+ if val.CanInterface() {
+ if marshaler, ok := reflect.TypeAssert[Marshaler](val); ok {
+ return p.marshalInterface(marshaler, defaultStart(typ, finfo, startTemplate))
+ }
}
if val.CanAddr() {
pv := val.Addr()
- if pv.CanInterface() && pv.Type().Implements(marshalerType) {
- return p.marshalInterface(pv.Interface().(Marshaler), defaultStart(pv.Type(), finfo, startTemplate))
+ if pv.CanInterface() {
+ if marshaler, ok := reflect.TypeAssert[Marshaler](pv); ok {
+ return p.marshalInterface(marshaler, defaultStart(pv.Type(), finfo, startTemplate))
+ }
}
}
// Check for text marshaler.
- if val.CanInterface() && typ.Implements(textMarshalerType) {
- return p.marshalTextInterface(val.Interface().(encoding.TextMarshaler), defaultStart(typ, finfo, startTemplate))
+ if val.CanInterface() {
+ if textMarshaler, ok := reflect.TypeAssert[encoding.TextMarshaler](val); ok {
+ return p.marshalTextInterface(textMarshaler, defaultStart(typ, finfo, startTemplate))
+ }
}
if val.CanAddr() {
pv := val.Addr()
- if pv.CanInterface() && pv.Type().Implements(textMarshalerType) {
- return p.marshalTextInterface(pv.Interface().(encoding.TextMarshaler), defaultStart(pv.Type(), finfo, startTemplate))
+ if pv.CanInterface() {
+ if textMarshaler, ok := reflect.TypeAssert[encoding.TextMarshaler](pv); ok {
+ return p.marshalTextInterface(textMarshaler, defaultStart(pv.Type(), finfo, startTemplate))
+ }
}
}
@@ -503,7 +505,7 @@ func (p *printer) marshalValue(val reflect.Value, finfo *fieldInfo, startTemplat
start.Name.Space, start.Name.Local = xmlname.xmlns, xmlname.name
} else {
fv := xmlname.value(val, dontInitNilPointers)
- if v, ok := fv.Interface().(Name); ok && v.Local != "" {
+ if v, ok := reflect.TypeAssert[Name](fv); ok && v.Local != "" {
start.Name = v
}
}
@@ -580,21 +582,9 @@ func (p *printer) marshalValue(val reflect.Value, finfo *fieldInfo, startTemplat
// marshalAttr marshals an attribute with the given name and value, adding to start.Attr.
func (p *printer) marshalAttr(start *StartElement, name Name, val reflect.Value) error {
- if val.CanInterface() && val.Type().Implements(marshalerAttrType) {
- attr, err := val.Interface().(MarshalerAttr).MarshalXMLAttr(name)
- if err != nil {
- return err
- }
- if attr.Name.Local != "" {
- start.Attr = append(start.Attr, attr)
- }
- return nil
- }
-
- if val.CanAddr() {
- pv := val.Addr()
- if pv.CanInterface() && pv.Type().Implements(marshalerAttrType) {
- attr, err := pv.Interface().(MarshalerAttr).MarshalXMLAttr(name)
+ if val.CanInterface() {
+ if marshaler, ok := reflect.TypeAssert[MarshalerAttr](val); ok {
+ attr, err := marshaler.MarshalXMLAttr(name)
if err != nil {
return err
}
@@ -605,19 +595,25 @@ func (p *printer) marshalAttr(start *StartElement, name Name, val reflect.Value)
}
}
- if val.CanInterface() && val.Type().Implements(textMarshalerType) {
- text, err := val.Interface().(encoding.TextMarshaler).MarshalText()
- if err != nil {
- return err
+ if val.CanAddr() {
+ pv := val.Addr()
+ if pv.CanInterface() {
+ if marshaler, ok := reflect.TypeAssert[MarshalerAttr](pv); ok {
+ attr, err := marshaler.MarshalXMLAttr(name)
+ if err != nil {
+ return err
+ }
+ if attr.Name.Local != "" {
+ start.Attr = append(start.Attr, attr)
+ }
+ return nil
+ }
}
- start.Attr = append(start.Attr, Attr{name, string(text)})
- return nil
}
- if val.CanAddr() {
- pv := val.Addr()
- if pv.CanInterface() && pv.Type().Implements(textMarshalerType) {
- text, err := pv.Interface().(encoding.TextMarshaler).MarshalText()
+ if val.CanInterface() {
+ if textMarshaler, ok := reflect.TypeAssert[encoding.TextMarshaler](val); ok {
+ text, err := textMarshaler.MarshalText()
if err != nil {
return err
}
@@ -626,6 +622,20 @@ func (p *printer) marshalAttr(start *StartElement, name Name, val reflect.Value)
}
}
+ if val.CanAddr() {
+ pv := val.Addr()
+ if pv.CanInterface() {
+ if textMarshaler, ok := reflect.TypeAssert[encoding.TextMarshaler](pv); ok {
+ text, err := textMarshaler.MarshalText()
+ if err != nil {
+ return err
+ }
+ start.Attr = append(start.Attr, Attr{name, string(text)})
+ return nil
+ }
+ }
+ }
+
// Dereference or skip nil pointer, interface values.
switch val.Kind() {
case reflect.Pointer, reflect.Interface:
@@ -647,7 +657,8 @@ func (p *printer) marshalAttr(start *StartElement, name Name, val reflect.Value)
}
if val.Type() == attrType {
- start.Attr = append(start.Attr, val.Interface().(Attr))
+ attr, _ := reflect.TypeAssert[Attr](val)
+ start.Attr = append(start.Attr, attr)
return nil
}
@@ -854,20 +865,9 @@ func (p *printer) marshalStruct(tinfo *typeInfo, val reflect.Value) error {
if err := s.trim(finfo.parents); err != nil {
return err
}
- if vf.CanInterface() && vf.Type().Implements(textMarshalerType) {
- data, err := vf.Interface().(encoding.TextMarshaler).MarshalText()
- if err != nil {
- return err
- }
- if err := emit(p, data); err != nil {
- return err
- }
- continue
- }
- if vf.CanAddr() {
- pv := vf.Addr()
- if pv.CanInterface() && pv.Type().Implements(textMarshalerType) {
- data, err := pv.Interface().(encoding.TextMarshaler).MarshalText()
+ if vf.CanInterface() {
+ if textMarshaler, ok := reflect.TypeAssert[encoding.TextMarshaler](vf); ok {
+ data, err := textMarshaler.MarshalText()
if err != nil {
return err
}
@@ -877,6 +877,21 @@ func (p *printer) marshalStruct(tinfo *typeInfo, val reflect.Value) error {
continue
}
}
+ if vf.CanAddr() {
+ pv := vf.Addr()
+ if pv.CanInterface() {
+ if textMarshaler, ok := reflect.TypeAssert[encoding.TextMarshaler](pv); ok {
+ data, err := textMarshaler.MarshalText()
+ if err != nil {
+ return err
+ }
+ if err := emit(p, data); err != nil {
+ return err
+ }
+ continue
+ }
+ }
+ }
var scratch [64]byte
vf = indirect(vf)
@@ -902,7 +917,7 @@ func (p *printer) marshalStruct(tinfo *typeInfo, val reflect.Value) error {
return err
}
case reflect.Slice:
- if elem, ok := vf.Interface().([]byte); ok {
+ if elem, ok := reflect.TypeAssert[[]byte](vf); ok {
if err := emit(p, elem); err != nil {
return err
}