diff --git a/ChangeLog b/ChangeLog index 381e893..182d559 100644 --- a/ChangeLog +++ b/ChangeLog @@ -5,6 +5,7 @@ DATE Emmanuel Gil Peyrot - JID Prep (XEP-0328) - Client State Indication (XEP-0352) - OpenPGP for XMPP (XEP-0373) + - Bookmarks 2 (This Time it's Serious) (XEP-0402) - Anonymous unique occupant identifiers for MUCs (XEP-0421) * Breaking changes: - Presence constructors now take Into and assume Some. diff --git a/doap.xml b/doap.xml index e75603d..40b28e3 100644 --- a/doap.xml +++ b/doap.xml @@ -465,6 +465,14 @@ 0.1.0 + + + + complete + 0.3.0 + NEXT + + diff --git a/src/bookmarks2.rs b/src/bookmarks2.rs new file mode 100644 index 0000000..2a182f1 --- /dev/null +++ b/src/bookmarks2.rs @@ -0,0 +1,119 @@ +// Copyright (c) 2019 Emmanuel Gil Peyrot +// +// 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/. + +generate_attribute!( + /// Whether a conference bookmark should be joined automatically. + Autojoin, + "autojoin", + bool +); + +generate_element!( + /// A conference bookmark. + Conference, "conference", BOOKMARKS2, + attributes: [ + /// Whether a conference bookmark should be joined automatically. + autojoin: Default = "autojoin", + + /// A user-defined name for this conference. + name: Option = "name", + ], + children: [ + /// The nick the user will use to join this conference. + nick: Option = ("nick", BOOKMARKS2) => String, + + /// The password required to join this conference. + password: Option = ("password", BOOKMARKS2) => String + ] +); + +impl Conference { + /// Create a new conference. + pub fn new() -> Conference { + Conference { + autojoin: Autojoin::False, + name: None, + nick: None, + password: None, + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::util::compare_elements::NamespaceAwareCompare; + use crate::Element; + use std::convert::TryFrom; + use crate::pubsub::pubsub::Item as PubSubItem; + use crate::pubsub::event::PubSubEvent; + use crate::ns; + + #[cfg(target_pointer_width = "32")] + #[test] + fn test_size() { + assert_size!(Conference, 40); + } + + #[cfg(target_pointer_width = "64")] + #[test] + fn test_size() { + assert_size!(Conference, 80); + } + + #[test] + fn simple() { + let elem: Element = "".parse().unwrap(); + let elem1 = elem.clone(); + let conference = Conference::try_from(elem).unwrap(); + assert_eq!(conference.autojoin, Autojoin::False); + assert_eq!(conference.name, None); + assert_eq!(conference.nick, None); + assert_eq!(conference.password, None); + + let elem2 = Element::from(Conference::new()); + assert!(elem1.compare_to(&elem2)); + } + + #[test] + fn complete() { + let elem: Element = "Coucousecret".parse().unwrap(); + let conference = Conference::try_from(elem).unwrap(); + assert_eq!(conference.autojoin, Autojoin::True); + assert_eq!(conference.name, Some(String::from("Test MUC"))); + assert_eq!(conference.clone().nick.unwrap(), "Coucou"); + assert_eq!(conference.clone().password.unwrap(), "secret"); + } + + #[test] + fn wrapped() { + let elem: Element = "Coucousecret".parse().unwrap(); + let item = PubSubItem::try_from(elem).unwrap(); + let payload = item.payload.clone().unwrap(); + let conference = Conference::try_from(payload).unwrap(); + assert_eq!(conference.autojoin, Autojoin::True); + assert_eq!(conference.name, Some(String::from("Test MUC"))); + assert_eq!(conference.clone().nick.unwrap(), "Coucou"); + assert_eq!(conference.clone().password.unwrap(), "secret"); + + let elem: Element = "Coucousecret".parse().unwrap(); + let mut items = match PubSubEvent::try_from(elem) { + Ok(PubSubEvent::PublishedItems { node, items }) => { + assert_eq!(&node.0, ns::BOOKMARKS2); + items + }, + _ => panic!(), + }; + assert_eq!(items.len(), 1); + let item = items.pop().unwrap(); + let payload = item.payload.clone().unwrap(); + let conference = Conference::try_from(payload).unwrap(); + assert_eq!(conference.autojoin, Autojoin::True); + assert_eq!(conference.name, Some(String::from("Test MUC"))); + assert_eq!(conference.clone().nick.unwrap(), "Coucou"); + assert_eq!(conference.clone().password.unwrap(), "secret"); + } +} diff --git a/src/lib.rs b/src/lib.rs index b69e56a..2f856e0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -201,5 +201,8 @@ pub mod eme; /// XEP-0390: Entity Capabilities 2.0 pub mod ecaps2; +/// XEP-0402: Bookmarks 2 (This Time it's Serious) +pub mod bookmarks2; + /// XEP-0421: Anonymous unique occupant identifiers for MUCs pub mod occupant_id; diff --git a/src/ns.rs b/src/ns.rs index 70d68cf..5aea7a6 100644 --- a/src/ns.rs +++ b/src/ns.rs @@ -210,6 +210,11 @@ pub const ECAPS2: &str = "urn:xmpp:caps"; /// XEP-0390: Entity Capabilities 2.0 pub const ECAPS2_OPTIMIZE: &str = "urn:xmpp:caps:optimize"; +/// XEP-0402: Bookmarks 2 (This Time it's Serious) +pub const BOOKMARKS2: &str = "urn:xmpp:bookmarks:0"; +/// XEP-0402: Bookmarks 2 (This Time it's Serious) +pub const BOOKMARKS2_COMPAT: &str = "urn:xmpp:bookmarks:0#compat"; + /// XEP-0421: Anonymous unique occupant identifiers for MUCs pub const OID: &str = "urn:xmpp:occupant-id:0";