structs.go
branchgo.weekly.2012-01-15
changeset 93 fbd51fa6b7ea
parent 75 03a923eb5c01
child 94 0ef947611eec
--- a/structs.go	Mon Jan 23 21:58:53 2012 -0700
+++ b/structs.go	Sun Apr 15 11:20:55 2012 -0600
@@ -31,6 +31,7 @@
 
 // XMPP's <stream:stream> XML element
 type stream struct {
+	XMLName xml.Name `xml:"stream stream"`
 	To      string `xml:"to,attr"`
 	From    string `xml:"from,attr"`
 	Id      string `xml:"id,attr"`
@@ -38,30 +39,26 @@
 	Version string `xml:"version,attr"`
 }
 
-var _ xml.Marshaler = &stream{}
 var _ fmt.Stringer = &stream{}
 
 // <stream:error>
 type streamError struct {
-	Any  Generic `xml:",any"`
+	Any  Generic  `xml:",any"`
 	Text *errText `xml:"text"`
 }
 
-var _ xml.Marshaler = &streamError{}
-
 type errText struct {
+	XMLName xml.Name `xml:"urn:ietf:params:xml:ns:xmpp-streams text"`
 	Lang string `xml:"lang,attr"`
 	Text string `xml:",chardata"`
 }
 
-var _ xml.Marshaler = &errText{}
-
 type Features struct {
 	Starttls   *starttls `xml:"starttls"`
-	Mechanisms mechs `xml:"mechanisms"`
-	Bind       *bindIq `xml:"bind"`
-	Session    *Generic `xml:"session"`
-	Any        *Generic `xml:",any"`
+	Mechanisms mechs     `xml:"mechanisms"`
+	Bind       *bindIq   `xml:"bind"`
+	Session    *Generic  `xml:"session"`
+	Any        *Generic  `xml:",any"`
 }
 
 type starttls struct {
@@ -75,8 +72,8 @@
 
 type auth struct {
 	XMLName   xml.Name
-	Chardata  string `xml:",chardata"`
-	Mechanism string `xml:"mechanism,attr"`
+	Chardata  string   `xml:",chardata"`
+	Mechanism string   `xml:"mechanism,attr"`
 	Any       *Generic `xml:",any"`
 }
 
@@ -106,53 +103,53 @@
 
 // message stanza
 type Message struct {
-	To       string `xml:"to,attr"`
-	From     string `xml:"from,attr"`
-	Id       string `xml:"id,attr"`
-	Type     string `xml:"type,attr"`
-	Lang     string `xml:"lang,attr"`
-	Innerxml string `xml:",innerxml"`
-	Error    *Error `xml:"error"`
+	XMLName  xml.Name `xml:"message"`
+	To       string   `xml:"to,attr,omitempty"`
+	From     string   `xml:"from,attr,omitempty"`
+	Id       string   `xml:"id,attr,omitempty"`
+	Type     string   `xml:"type,attr,omitempty"`
+	Lang     string   `xml:"lang,attr,omitempty"`
+	Innerxml string   `xml:",innerxml"`
+	Error    *Error   `xml:"error"`
 	Subject  *Generic `xml:"subject"`
 	Body     *Generic `xml:"body"`
 	Thread   *Generic `xml:"thread"`
 	Nested   []interface{}
 }
 
-var _ xml.Marshaler = &Message{}
 var _ Stanza = &Message{}
 
 // presence stanza
 type Presence struct {
-	To       string `xml:"to,attr"`
-	From     string `xml:"from,attr"`
-	Id       string `xml:"id,attr"`
-	Type     string `xml:"type,attr"`
-	Lang     string `xml:"lang,attr"`
-	Innerxml string `xml:",innerxml"`
-	Error    *Error `xml:"error"`
+	XMLName  xml.Name `xml:"presence"`
+	To       string   `xml:"to,attr,omitempty"`
+	From     string   `xml:"from,attr,omitempty"`
+	Id       string   `xml:"id,attr,omitempty"`
+	Type     string   `xml:"type,attr,omitempty"`
+	Lang     string   `xml:"lang,attr,omitempty"`
+	Innerxml string   `xml:",innerxml"`
+	Error    *Error   `xml:"error"`
 	Show     *Generic `xml:"show"`
 	Status   *Generic `xml:"status"`
 	Priority *Generic `xml:"priority"`
 	Nested   []interface{}
 }
 
-var _ xml.Marshaler = &Presence{}
 var _ Stanza = &Presence{}
 
 // iq stanza
 type Iq struct {
-	To       string `xml:"to,attr"`
-	From     string `xml:"from,attr"`
-	Id       string `xml:"id,attr"`
-	Type     string `xml:"type,attr"`
-	Lang     string `xml:"lang,attr"`
+	XMLName  xml.Name `xml:"iq"`
+	To       string `xml:"to,attr,omitempty"`
+	From     string `xml:"from,attr,omitempty"`
+	Id       string `xml:"id,attr,omitempty"`
+	Type     string `xml:"type,attr,omitempty"`
+	Lang     string `xml:"xml lang,attr,omitempty"`
 	Innerxml string `xml:",innerxml"`
 	Error    *Error `xml:"error"`
 	Nested   []interface{}
 }
 
-var _ xml.Marshaler = &Iq{}
 var _ Stanza = &Iq{}
 
 // Describes an XMPP stanza error. See RFC 3920, Section 9.3.
@@ -177,7 +174,7 @@
 type Generic struct {
 	XMLName  xml.Name
 	Any      *Generic `xml:",any"`
-	Chardata string `xml:",chardata"`
+	Chardata string   `xml:",chardata"`
 }
 
 var _ fmt.Stringer = &Generic{}
@@ -207,24 +204,16 @@
 	return nil
 }
 
-func (s *stream) MarshalXML() ([]byte, error) {
+func (s *stream) String() string {
 	buf := bytes.NewBuffer(nil)
 	buf.WriteString("<stream:stream")
-	writeField(buf, "xmlns", "jabber:client")
-	writeField(buf, "xmlns:stream", NsStream)
 	writeField(buf, "to", s.To)
 	writeField(buf, "from", s.From)
 	writeField(buf, "id", s.Id)
 	writeField(buf, "xml:lang", s.Lang)
 	writeField(buf, "version", s.Version)
 	buf.WriteString(">")
-	// We never write </stream:stream>
-	return buf.Bytes(), nil
-}
-
-func (s *stream) String() string {
-	result, _ := s.MarshalXML()
-	return string(result)
+	return buf.String()
 }
 
 func parseStream(se xml.StartElement) (*stream, error) {
@@ -246,28 +235,6 @@
 	return s, nil
 }
 
-func (s *streamError) MarshalXML() ([]byte, error) {
-	buf := bytes.NewBuffer(nil)
-	buf.WriteString("<stream:error>")
-	xml.Marshal(buf, s.Any)
-	if s.Text != nil {
-		xml.Marshal(buf, s.Text)
-	}
-	buf.WriteString("</stream:error>")
-	return buf.Bytes(), nil
-}
-
-func (e *errText) MarshalXML() ([]byte, error) {
-	buf := bytes.NewBuffer(nil)
-	buf.WriteString("<text")
-	writeField(buf, "xmlns", NsStreams)
-	writeField(buf, "xml:lang", e.Lang)
-	buf.WriteString(">")
-	xml.Escape(buf, []byte(e.Text))
-	buf.WriteString("</text>")
-	return buf.Bytes(), nil
-}
-
 func writeField(w io.Writer, field, value string) {
 	if value != "" {
 		io.WriteString(w, " ")
@@ -291,72 +258,9 @@
 		u.XMLName.Local)
 }
 
-func marshalXML(st Stanza) ([]byte, error) {
-	buf := bytes.NewBuffer(nil)
-	buf.WriteString("<")
-	buf.WriteString(st.GetName())
-	if st.GetTo() != "" {
-		writeField(buf, "to", st.GetTo())
-	}
-	if st.GetFrom() != "" {
-		writeField(buf, "from", st.GetFrom())
-	}
-	if st.GetId() != "" {
-		writeField(buf, "id", st.GetId())
-	}
-	if st.GetType() != "" {
-		writeField(buf, "type", st.GetType())
-	}
-	if st.GetLang() != "" {
-		writeField(buf, "xml:lang", st.GetLang())
-	}
-	buf.WriteString(">")
-
-	if m, ok := st.(*Message); ok {
-		err := xml.Marshal(buf, m.Subject)
-		if err != nil {
-			return nil, err
-		}
-		err = xml.Marshal(buf, m.Body)
-		if err != nil {
-			return nil, err
-		}
-		err = xml.Marshal(buf, m.Thread)
-		if err != nil {
-			return nil, err
-		}
-	}
-	if p, ok := st.(*Presence); ok {
-		err := xml.Marshal(buf, p.Show)
-		if err != nil {
-			return nil, err
-		}
-		err = xml.Marshal(buf, p.Status)
-		if err != nil {
-			return nil, err
-		}
-		err = xml.Marshal(buf, p.Priority)
-		if err != nil {
-			return nil, err
-		}
-	}
-	if nested := st.GetNested(); nested != nil {
-		for _, n := range nested {
-			xml.Marshal(buf, n)
-		}
-	} else if st.innerxml() != "" {
-		buf.WriteString(st.innerxml())
-	}
-
-	buf.WriteString("</")
-	buf.WriteString(st.GetName())
-	buf.WriteString(">")
-	return buf.Bytes(), nil
-}
-
 func (er *Error) Error() string {
 	buf := bytes.NewBuffer(nil)
-	xml.Marshal(buf, er)
+	xml.NewEncoder(buf).Encode(er)
 	return buf.String()
 }
 
@@ -400,10 +304,6 @@
 	return m.Innerxml
 }
 
-func (m *Message) MarshalXML() ([]byte, error) {
-	return marshalXML(m)
-}
-
 func (p *Presence) GetName() string {
 	return "presence"
 }
@@ -444,10 +344,6 @@
 	return p.Innerxml
 }
 
-func (p *Presence) MarshalXML() ([]byte, error) {
-	return marshalXML(p)
-}
-
 func (iq *Iq) GetName() string {
 	return "iq"
 }
@@ -488,15 +384,11 @@
 	return iq.Innerxml
 }
 
-func (iq *Iq) MarshalXML() ([]byte, error) {
-	return marshalXML(iq)
-}
-
 // Parse a string into a struct implementing Stanza -- this will be
 // either an Iq, a Message, or a Presence.
 func ParseStanza(str string) (Stanza, error) {
 	r := strings.NewReader(str)
-	p := xml.NewParser(r)
+	p := xml.NewDecoder(r)
 	tok, err := p.Token()
 	if err != nil {
 		return nil, err
@@ -516,7 +408,7 @@
 	default:
 		return nil, errors.New("Not iq, message, or presence")
 	}
-	err = p.Unmarshal(stan, &se)
+	err = p.DecodeElement(stan, &se)
 	if err != nil {
 		return nil, err
 	}