Detailed changes
@@ -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"
@@ -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;
@@ -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.");
+ }
+}
@@ -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";
@@ -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(),