Step 1 of moving to interface Stanza and embedded struct Header.
authorChris Jones <chris@cjones.org>
Sun, 16 Dec 2012 22:36:53 -0700
changeset 111 36287f2cf06e
parent 110 7696e6a01709
child 112 bd56fb741f69
Step 1 of moving to interface Stanza and embedded struct Header.
roster.go
roster_test.go
stream.go
structs.go
structs_test.go
xmpp.go
--- a/roster.go	Sun Dec 16 22:17:49 2012 -0700
+++ b/roster.go	Sun Dec 16 22:36:53 2012 -0700
@@ -48,7 +48,7 @@
 func fetchRoster(client *Client) error {
 	rosterUpdate := rosterClients[client.Uid].rosterUpdate
 
-	iq := &Iq{Stanza: Stanza{From: client.Jid.String(), Type: "get",
+	iq := &Iq{Header: Header{From: client.Jid.String(), Type: "get",
 		Id: <-Id, Nested: []interface{}{RosterQuery{}}}}
 	ch := make(chan error)
 	f := func(v interface{}) bool {
@@ -128,7 +128,7 @@
 			rosterUpdate <- item
 		}
 		// Send a reply.
-		reply := &Iq{Stanza: Stanza{To: iq.From, Id: iq.Id,
+		reply := &Iq{Header: Header{To: iq.From, Id: iq.Id,
 			Type: "result"}}
 		client.Out <- reply
 	}
--- a/roster_test.go	Sun Dec 16 22:17:49 2012 -0700
+++ b/roster_test.go	Sun Dec 16 22:36:53 2012 -0700
@@ -13,7 +13,7 @@
 // This is mostly just tests of the roster data structures.
 
 func TestRosterIqMarshal(t *testing.T) {
-	iq := &Iq{Stanza: Stanza{From: "from", Lang: "en",
+	iq := &Iq{Header: Header{From: "from", Lang: "en",
 		Nested: []interface{}{RosterQuery{}}}}
 	exp := `<iq from="from" xml:lang="en"><query xmlns="` +
 		NsRoster + `"></query></iq>`
@@ -26,7 +26,7 @@
 	iq := Iq{}
 	xml.Unmarshal([]byte(str), &iq)
 	m := map[string]func(*xml.Name) interface{}{NsRoster: newRosterQuery}
-	err := parseExtended(&iq.Stanza, m)
+	err := parseExtended(&iq.Header, m)
 	if err != nil {
 		t.Fatalf("parseExtended: %v", err)
 	}
--- a/stream.go	Sun Dec 16 22:17:49 2012 -0700
+++ b/stream.go	Sun Dec 16 22:36:53 2012 -0700
@@ -148,8 +148,8 @@
 		// If it's a Stanza, we try to unmarshal its innerxml
 		// into objects of the appropriate respective
 		// types. This is specified by our extensions.
-		if st := getStanza(obj) ; st != nil {
-			err = parseExtended(st, extStanza)
+		if st, ok := obj.(Stanzer) ; ok {
+			err = parseExtended(st.GetHeader(), extStanza)
 			if err != nil {
 				Warn.Logf("ext unmarshal: %s", err)
 				break Loop
@@ -161,7 +161,7 @@
 	}
 }
 
-func parseExtended(st *Stanza, extStanza map[string]func(*xml.Name) interface{}) error {
+func parseExtended(st *Header, extStanza map[string]func(*xml.Name) interface{}) error {
 	// Now parse the stanza's innerxml to find the string that we
 	// can unmarshal this nested element from.
 	reader := strings.NewReader(st.Innerxml)
@@ -238,7 +238,7 @@
 			if !ok {
 				break Loop
 			}
-			var st *Stanza
+			var st *Header
 			switch obj := x.(type) {
 			case *stream:
 				handleStream(obj)
@@ -250,8 +250,8 @@
 				cl.handleTls(obj)
 			case *auth:
 				cl.handleSasl(obj)
-			case *Iq, *Message, *Presence:
-				st = getStanza(obj)
+			case Stanzer:
+				st = obj.GetHeader()
 			default:
 				Warn.Logf("Unhandled non-stanza: %T %#v", x, x)
 			}
@@ -596,7 +596,7 @@
 	if res != "" {
 		bindReq.Resource = &res
 	}
-	msg := &Iq{Stanza: Stanza{Type: "set", Id: <-Id,
+	msg := &Iq{Header: Header{Type: "set", Id: <-Id,
 		Nested: []interface{}{bindReq}}}
 	f := func(st interface{}) bool {
 		iq, ok := st.(*Iq)
--- a/structs.go	Sun Dec 16 22:17:49 2012 -0700
+++ b/structs.go	Sun Dec 16 22:36:53 2012 -0700
@@ -77,9 +77,13 @@
 	Any       *Generic
 }
 
+type Stanzer interface {
+	GetHeader() *Header
+}
+
 // One of the three core XMPP stanza types: iq, message, presence. See
 // RFC3920, section 9.
-type Stanza struct {
+type Header struct {
 	To       string   `xml:"to,attr,omitempty"`
 	From     string   `xml:"from,attr,omitempty"`
 	Id       string   `xml:"id,attr,omitempty"`
@@ -93,26 +97,29 @@
 // message stanza
 type Message struct {
 	XMLName  xml.Name `xml:"message"`
-	Stanza
+	Header
 	Subject  *Generic `xml:"subject"`
 	Body     *Generic `xml:"body"`
 	Thread   *Generic `xml:"thread"`
 }
+var _ Stanzer = &Message{}
 
 // presence stanza
 type Presence struct {
 	XMLName  xml.Name `xml:"presence"`
-	Stanza
+	Header
 	Show     *Generic `xml:"show"`
 	Status   *Generic `xml:"status"`
 	Priority *Generic `xml:"priority"`
 }
+var _ Stanzer = &Presence{}
 
 // iq stanza
 type Iq struct {
 	XMLName  xml.Name `xml:"iq"`
-	Stanza
+	Header
 }
+var _ Stanzer = &Iq{}
 
 // Describes an XMPP stanza error. See RFC 3920, Section 9.3.
 type Error struct {
@@ -222,6 +229,18 @@
 	return s, nil
 }
 
+func (iq *Iq) GetHeader() *Header {
+	return &iq.Header
+}
+
+func (m *Message) GetHeader() *Header {
+	return &m.Header
+}
+
+func (p *Presence) GetHeader() *Header {
+	return &p.Header
+}
+
 func (u *Generic) String() string {
 	if u == nil {
 		return "nil"
@@ -250,15 +269,3 @@
 func newBind(name *xml.Name) interface{} {
 	return &bindIq{}
 }
-
-func getStanza(v interface{}) *Stanza {
-	switch s := v.(type) {
-	case *Iq:
-		return &s.Stanza
-	case *Message:
-		return &s.Stanza
-	case *Presence:
-		return &s.Stanza
-	}
-	return nil
-}
--- a/structs_test.go	Sun Dec 16 22:17:49 2012 -0700
+++ b/structs_test.go	Sun Dec 16 22:36:53 2012 -0700
@@ -89,7 +89,7 @@
 }
 
 func TestIqMarshal(t *testing.T) {
-	iq := &Iq{Stanza: Stanza{Type: "set", Id: "3",
+	iq := &Iq{Header: Header{Type: "set", Id: "3",
 		Nested: []interface{}{Generic{XMLName: xml.Name{Space: NsBind,
 			Local: "bind"}}}}}
 	exp := `<iq id="3" type="set"><bind xmlns="` + NsBind +
--- a/xmpp.go	Sun Dec 16 22:17:49 2012 -0700
+++ b/xmpp.go	Sun Dec 16 22:36:53 2012 -0700
@@ -268,7 +268,7 @@
 // Presence struct.  See RFC 3921, Section 3.
 func (cl *Client) StartSession(getRoster bool, pr *Presence) error {
 	id := <-Id
-	iq := &Iq{Stanza: Stanza{To: cl.Jid.Domain, Id: id, Type: "set",
+	iq := &Iq{Header: Header{To: cl.Jid.Domain, Id: id, Type: "set",
 		Nested: []interface{}{Generic{XMLName:
 			xml.Name{Space: NsSession, Local: "session"}}}}}
 	ch := make(chan error)