~samwhited/xmpp

8265074653987f86c203c8560a9270035e1043ff — Sam Whited 1 year, 9 months ago a9425fa
internal: add XML struct encoding workaround

This is a very inefficient work around for the encoding/xml package not
supporting any way to encode to a token stream.
Hopefully it will eventually be replaced if the encoding/xml package
ever gets updated.
1 files changed, 64 insertions(+), 0 deletions(-)

A internal/encode.go
A internal/encode.go => internal/encode.go +64 -0
@@ 0,0 1,64 @@
// Copyright 2019 The Mellium Contributors.
// Use of this source code is governed by the BSD 2-clause
// license that can be found in the LICENSE file.

package internal

import (
	"bytes"
	"encoding/xml"

	"mellium.im/xmlstream"
)

// TODO: functions in this file are very inefficient, but doing it in a saner
// way requires significant changes to encoding/xml.

// EncodeXML writes the XML encoding of v to the stream.
//
// See the documentation for xml.Marshal for details about the conversion of Go
// values to XML.
//
// If the stream is an xmlstream.Flusher, EncodeXML calls Flush before
// returning.
func EncodeXML(w xmlstream.TokenWriter, v interface{}) error {
	var b bytes.Buffer
	err := xml.NewEncoder(&b).Encode(v)
	if err != nil {
		return err
	}
	_, err = xmlstream.Copy(w, xml.NewDecoder(&b))
	if err != nil {
		return err
	}

	if wf, ok := w.(xmlstream.Flusher); ok {
		return wf.Flush()
	}
	return nil
}

// EncodeXMLElement writes the XML encoding of v to the stream, using start as
// the outermost tag in the encoding.
//
// See the documentation for xml.Marshal for details about the conversion of Go
// values to XML.
//
// If the stream is an xmlstream.Flusher, EncodeXMLElement calls Flush before
// returning.
func EncodeXMLElement(w xmlstream.TokenWriter, v interface{}, start xml.StartElement) error {
	var b bytes.Buffer
	err := xml.NewEncoder(&b).EncodeElement(v, start)
	if err != nil {
		return err
	}
	_, err = xmlstream.Copy(w, xml.NewDecoder(&b))
	if err != nil {
		return err
	}

	if wf, ok := w.(xmlstream.Flusher); ok {
		return wf.Flush()
	}
	return nil
}