structs.go
changeset 12 122ab6208c3c
parent 11 48be1ae93fd4
child 17 d269d9c0fc8e
--- a/structs.go	Tue Dec 27 15:36:07 2011 -0700
+++ b/structs.go	Tue Dec 27 20:42:44 2011 -0700
@@ -21,9 +21,10 @@
 // entities. It looks like node@domain/resource. Node and resource are
 // sometimes optional.
 type JID struct {
+	// TODO Make this not a pointer.
 	Node *string
 	Domain string
-	Resource *string
+	Resource string
 }
 var _ fmt.Stringer = &JID{}
 var _ flag.Value = &JID{}
@@ -61,6 +62,7 @@
 type Features struct {
 	Starttls *starttls
 	Mechanisms mechs
+	Bind *Unrecognized
 }
 
 type starttls struct {
@@ -79,8 +81,64 @@
 	Any *Unrecognized
 }
 
+type Stanza interface {
+	XName() string
+	XTo() string
+	XFrom() string
+	XId() string
+	XType() string
+	XLang() string
+	XError() *Error
+	XChild() *Unrecognized
+}
+
+type Message struct {
+	To string `xml:"attr"`
+	From string `xml:"attr"`
+	Id string `xml:"attr"`
+	Type string `xml:"attr"`
+	Lang string `xml:"attr"`
+	Error *Error
+	Any *Unrecognized
+}
+var _ xml.Marshaler = &Message{}
+var _ Stanza = &Message{}
+
+type Presence struct {
+	To string `xml:"attr"`
+	From string `xml:"attr"`
+	Id string `xml:"attr"`
+	Type string `xml:"attr"`
+	Lang string `xml:"attr"`
+	Error *Error
+	Any *Unrecognized
+}
+var _ xml.Marshaler = &Presence{}
+var _ Stanza = &Presence{}
+
+type Iq struct {
+	To string `xml:"attr"`
+	From string `xml:"attr"`
+	Id string `xml:"attr"`
+	Type string `xml:"attr"`
+	Lang string `xml:"attr"`
+	Error *Error
+	Any *Unrecognized
+}
+var _ xml.Marshaler = &Iq{}
+var _ Stanza = &Iq{}
+
+type Error struct {
+	Type string `xml:"attr"`
+	Any *Unrecognized
+}
+var _ xml.Marshaler = &Error{}
+
+// TODO Rename this to something like Generic.
 type Unrecognized struct {
 	XMLName xml.Name
+	Any *Unrecognized
+	Chardata string `xml:"chardata"`
 }
 var _ fmt.Stringer = &Unrecognized{}
 
@@ -89,8 +147,8 @@
 	if jid.Node != nil {
 		result = *jid.Node + "@" + result
 	}
-	if jid.Resource != nil {
-		result = result + "/" + *jid.Resource
+	if jid.Resource != "" {
+		result = result + "/" + jid.Resource
 	}
 	return result
 }
@@ -107,11 +165,7 @@
 		jid.Node = &parts[2]
 	}
 	jid.Domain = parts[3]
-	if parts[5] == "" {
-		jid.Resource = nil
-	} else {
-		jid.Resource = &parts[5]
-	}
+	jid.Resource = parts[5]
 	return true
 }
 
@@ -187,6 +241,164 @@
 }
 
 func (u *Unrecognized) String() string {
-	return fmt.Sprintf("unrecognized{%s %s}", u.XMLName.Space,
+	var sub string
+	if u.Any != nil {
+		sub = u.Any.String()
+	}
+	return fmt.Sprintf("<%s %s>%s%s</%s %s>", u.XMLName.Space,
+		u.XMLName.Local, sub, u.Chardata, u.XMLName.Space,
 		u.XMLName.Local)
 }
+
+func marshalXML(st Stanza) ([]byte, os.Error) {
+	buf := bytes.NewBuffer(nil)
+	buf.WriteString("<")
+	buf.WriteString(st.XName())
+	if st.XTo() != "" {
+		writeField(buf, "to", st.XTo())
+	}
+	if st.XFrom() != "" {
+		writeField(buf, "from", st.XFrom())
+	}
+	if st.XId() != "" {
+		writeField(buf, "id", st.XId())
+	}
+	if st.XType() != "" {
+		writeField(buf, "type", st.XType())
+	}
+	if st.XLang() != "" {
+		writeField(buf, "xml:lang", st.XLang())
+	}
+	buf.WriteString(">")
+	if st.XError() != nil {
+		bytes, _ := st.XError().MarshalXML()
+		buf.WriteString(string(bytes))
+	}
+	if st.XChild() != nil {
+		xml.Marshal(buf, st.XChild())
+	}
+	buf.WriteString("</")
+	buf.WriteString(st.XName())
+	buf.WriteString(">")
+	return buf.Bytes(), nil
+}
+
+func (er *Error) MarshalXML() ([]byte, os.Error) {
+	buf := bytes.NewBuffer(nil)
+	buf.WriteString("<error")
+	writeField(buf, "type", er.Type)
+	buf.WriteString(">")
+	if er.Any != nil {
+		xml.Marshal(buf, er.Any)
+	}
+	buf.WriteString("</error>")
+	return buf.Bytes(), nil
+}
+
+func (m *Message) XName() string {
+	return "message"
+}
+
+func (m *Message) XTo() string {
+	return m.To
+}
+
+func (m *Message) XFrom() string {
+	return m.From
+}
+
+func (m *Message) XId() string {
+	return m.Id
+}
+
+func (m *Message) XType() string {
+	return m.Type
+	}
+
+func (m *Message) XLang() string {
+	return m.Lang
+}
+
+func (m *Message) XError() *Error {
+	return m.Error
+}
+
+func (m *Message) XChild() *Unrecognized {
+	return m.Any
+}
+
+func (m *Message) MarshalXML() ([]byte, os.Error) {
+	return marshalXML(m)
+}
+
+func (p *Presence) XName() string {
+	return "presence"
+}
+
+func (p *Presence) XTo() string {
+	return p.To
+}
+
+func (p *Presence) XFrom() string {
+	return p.From
+}
+
+func (p *Presence) XId() string {
+	return p.Id
+}
+
+func (p *Presence) XType() string {
+	return p.Type
+	}
+
+func (p *Presence) XLang() string {
+	return p.Lang
+}
+
+func (p *Presence) XError() *Error {
+	return p.Error
+}
+
+func (p *Presence) XChild() *Unrecognized {
+	return p.Any
+}
+
+func (p *Presence) MarshalXML() ([]byte, os.Error) {
+	return marshalXML(p)
+}
+
+func (iq *Iq) XName() string {
+	return "iq"
+}
+
+func (iq *Iq) XTo() string {
+	return iq.To
+}
+
+func (iq *Iq) XFrom() string {
+	return iq.From
+}
+
+func (iq *Iq) XId() string {
+	return iq.Id
+}
+
+func (iq *Iq) XType() string {
+	return iq.Type
+	}
+
+func (iq *Iq) XLang() string {
+	return iq.Lang
+}
+
+func (iq *Iq) XError() *Error {
+	return iq.Error
+}
+
+func (iq *Iq) XChild() *Unrecognized {
+	return iq.Any
+}
+
+func (iq *Iq) MarshalXML() ([]byte, os.Error) {
+	return marshalXML(iq)
+}