diff --git a/Cargo.toml b/Cargo.toml index 84fe4add..1a93c909 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,10 @@ [package] name = "xmpp-parsers" version = "0.4.0" -authors = ["Emmanuel Gil Peyrot "] +authors = [ + "Emmanuel Gil Peyrot ", + "Maxime “pep” Buquet ", +] description = "Collection of parsers and serialisers for XMPP extensions" homepage = "https://hg.linkmauve.fr/xmpp-parsers" repository = "https://hg.linkmauve.fr/xmpp-parsers" diff --git a/src/lib.rs b/src/lib.rs index c6f11031..b5ee57ef 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -7,6 +7,7 @@ //! back before being sent over the wire. // Copyright (c) 2017 Emmanuel Gil Peyrot +// Copyright (c) 2017 Maxime “pep” Buquet // // 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; diff --git a/src/muc.rs b/src/muc.rs new file mode 100644 index 00000000..12923fc0 --- /dev/null +++ b/src/muc.rs @@ -0,0 +1,82 @@ +// Copyright (c) 2017 Maxime “pep” Buquet +// +// 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 for Muc { + type Error = Error; + + fn try_from(elem: Element) -> Result { + 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 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 = "".parse().unwrap(); + Muc::try_from(elem).unwrap(); + } + + #[test] + fn test_invalid_child() { + let elem: Element = "".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 = "".parse().unwrap(); + let muc = Muc; + let elem2 = muc.into(); + assert_eq!(elem, elem2); + } + + #[test] + fn test_invalid_attribute() { + let elem: Element = "".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."); + } +} diff --git a/src/ns.rs b/src/ns.rs index 4f563e62..d7706617 100644 --- a/src/ns.rs +++ b/src/ns.rs @@ -1,4 +1,5 @@ // Copyright (c) 2017 Emmanuel Gil Peyrot +// Copyright (c) 2017 Maxime “pep” Buquet // // 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"; diff --git a/src/presence.rs b/src/presence.rs index b359eb5e..d04a3d2e 100644 --- a/src/presence.rs +++ b/src/presence.rs @@ -1,4 +1,5 @@ // Copyright (c) 2017 Emmanuel Gil Peyrot +// Copyright (c) 2017 Maxime “pep” Buquet // // 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 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 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(),