Muc <x xmlns='http://jabber.org/protocol/muc'/> parser

Maxime “pep” Buquet created

Change summary

Cargo.toml      |  5 ++
src/lib.rs      |  4 ++
src/muc.rs      | 82 +++++++++++++++++++++++++++++++++++++++++++++++++++
src/ns.rs       |  4 ++
src/presence.rs |  7 ++++
5 files changed, 101 insertions(+), 1 deletion(-)

Detailed changes

Cargo.toml 🔗

@@ -1,7 +1,10 @@
 [package]
 name = "xmpp-parsers"
 version = "0.4.0"
-authors = ["Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>"]
+authors = [
+  "Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>",
+  "Maxime “pep” Buquet <pep+code@bouah.net>",
+]
 description = "Collection of parsers and serialisers for XMPP extensions"
 homepage = "https://hg.linkmauve.fr/xmpp-parsers"
 repository = "https://hg.linkmauve.fr/xmpp-parsers"

src/lib.rs 🔗

@@ -7,6 +7,7 @@
 //! back before being sent over the wire.
 
 // Copyright (c) 2017 Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
+// Copyright (c) 2017 Maxime “pep” Buquet <pep+code@bouah.net>
 //
 // This Source Code Form is subject to the terms of the Mozilla Public
 // License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -71,6 +72,9 @@ pub mod data_forms;
 /// XEP-0030: Service Discovery
 pub mod disco;
 
+/// XEP-0045: Multi-User Chat
+pub mod muc;
+
 /// XEP-0047: In-Band Bytestreams
 pub mod ibb;
 

src/muc.rs 🔗

@@ -0,0 +1,82 @@
+// Copyright (c) 2017 Maxime “pep” Buquet <pep+code@bouah.net>
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+use std::convert::TryFrom;
+
+use minidom::Element;
+
+use error::Error;
+
+use ns;
+
+#[derive(Debug, Clone)]
+pub struct Muc;
+
+impl TryFrom<Element> for Muc {
+    type Error = Error;
+
+    fn try_from(elem: Element) -> Result<Muc, Error> {
+        if !elem.is("x", ns::MUC) {
+            return Err(Error::ParseError("This is not an x element."));
+        }
+        for _ in elem.children() {
+            return Err(Error::ParseError("Unknown child in x element."));
+        }
+        for _ in elem.attrs() {
+            return Err(Error::ParseError("Unknown attribute in x element."));
+        }
+        Ok(Muc)
+    }
+}
+
+impl Into<Element> for Muc {
+    fn into(self) -> Element {
+        Element::builder("x")
+                .ns(ns::MUC)
+                .build()
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn test_simple() {
+        let elem: Element = "<x xmlns='http://jabber.org/protocol/muc'/>".parse().unwrap();
+        Muc::try_from(elem).unwrap();
+    }
+
+    #[test]
+    fn test_invalid_child() {
+        let elem: Element = "<x xmlns='http://jabber.org/protocol/muc'><coucou/></x>".parse().unwrap();
+        let error = Muc::try_from(elem).unwrap_err();
+        let message = match error {
+            Error::ParseError(string) => string,
+            _ => panic!(),
+        };
+        assert_eq!(message, "Unknown child in x element.");
+    }
+
+    #[test]
+    fn test_serialise() {
+        let elem: Element = "<x xmlns='http://jabber.org/protocol/muc'/>".parse().unwrap();
+        let muc = Muc;
+        let elem2 = muc.into();
+        assert_eq!(elem, elem2);
+    }
+
+    #[test]
+    fn test_invalid_attribute() {
+        let elem: Element = "<x xmlns='http://jabber.org/protocol/muc' coucou=''/>".parse().unwrap();
+        let error = Muc::try_from(elem).unwrap_err();
+        let message = match error {
+            Error::ParseError(string) => string,
+            _ => panic!(),
+        };
+        assert_eq!(message, "Unknown attribute in x element.");
+    }
+}

src/ns.rs 🔗

@@ -1,4 +1,5 @@
 // Copyright (c) 2017 Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
+// Copyright (c) 2017 Maxime “pep” Buquet <pep+code@bouah.net>
 //
 // This Source Code Form is subject to the terms of the Mozilla Public
 // License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -18,6 +19,9 @@ pub const DATA_FORMS: &'static str = "jabber:x:data";
 /// XEP-0030: Service Discovery
 pub const DISCO_INFO: &'static str = "http://jabber.org/protocol/disco#info";
 
+/// XEP-0045: Multi-User Chat
+pub const MUC: &'static str = "http://jabber.org/protocol/muc";
+
 /// XEP-0047: In-Band Bytestreams
 pub const IBB: &'static str = "http://jabber.org/protocol/ibb";
 

src/presence.rs 🔗

@@ -1,4 +1,5 @@
 // Copyright (c) 2017 Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
+// Copyright (c) 2017 Maxime “pep” Buquet <pep+code@bouah.net>
 //
 // This Source Code Form is subject to the terms of the Mozilla Public
 // License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -17,6 +18,7 @@ use error::Error;
 use ns;
 
 use stanza_error::StanzaError;
+use muc::Muc;
 use caps::Caps;
 use delay::Delay;
 use idle::Idle;
@@ -79,6 +81,7 @@ pub type Priority = i8;
 #[derive(Debug, Clone)]
 pub enum PresencePayload {
     StanzaError(StanzaError),
+    Muc(Muc),
     Caps(Caps),
     Delay(Delay),
     Idle(Idle),
@@ -94,6 +97,9 @@ impl TryFrom<Element> for PresencePayload {
         Ok(match (elem.name().as_ref(), elem.ns().unwrap().as_ref()) {
             ("error", ns::JABBER_CLIENT) => PresencePayload::StanzaError(StanzaError::try_from(elem)?),
 
+            // XEP-0045
+            ("x", ns::MUC) => PresencePayload::Muc(Muc::try_from(elem)?),
+
             // XEP-0115
             ("c", ns::CAPS) => PresencePayload::Caps(Caps::try_from(elem)?),
 
@@ -115,6 +121,7 @@ impl Into<Element> for PresencePayload {
     fn into(self) -> Element {
         match self {
             PresencePayload::StanzaError(stanza_error) => stanza_error.into(),
+            PresencePayload::Muc(muc) => muc.into(),
             PresencePayload::Caps(caps) => caps.into(),
             PresencePayload::Delay(delay) => delay.into(),
             PresencePayload::Idle(idle) => idle.into(),