diff --git a/src/blocking.rs b/src/blocking.rs new file mode 100644 index 00000000..084844e6 --- /dev/null +++ b/src/blocking.rs @@ -0,0 +1,165 @@ +// Copyright (c) 2017 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/. + +use try_from::TryFrom; + +use jid::Jid; +use minidom::Element; + +use error::Error; + +use ns; + +generate_empty_element!(BlocklistRequest, "blocklist", ns::BLOCKING); + +fn get_children_items(elem: Element) -> Result, Error> { + let mut items = vec!(); + for child in elem.children() { + check_self!(child, "item", ns::BLOCKING); + check_no_unknown_attributes!(child, "item", ["jid"]); + check_no_children!(child, "item"); + items.push(get_attr!(child, "jid", required)); + } + Ok(items) +} + +macro_rules! generate_blocking_element { + ($elem:ident, $name:tt) => ( + #[derive(Debug, Clone)] + pub struct $elem { + pub items: Vec, + } + + impl TryFrom for $elem { + type Err = Error; + + fn try_from(elem: Element) -> Result<$elem, Error> { + check_self!(elem, $name, ns::BLOCKING); + check_no_attributes!(elem, $name); + Ok($elem { + items: get_children_items(elem)?, + }) + } + } + + impl From<$elem> for Element { + fn from(elem: $elem) -> Element { + Element::builder($name) + .ns(ns::BLOCKING) + .append(elem.items.into_iter().map(|jid| { + Element::builder("item") + .ns(ns::BLOCKING) + .attr("jid", jid) + .build() + }).collect::>()) + .build() + } + } + ); +} + +generate_blocking_element!(BlocklistResult, "blocklist"); +generate_blocking_element!(Block, "block"); +generate_blocking_element!(Unblock, "unblock"); + +generate_empty_element!(Blocked, "blocked", ns::BLOCKING_ERRORS); + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_simple() { + let elem: Element = "".parse().unwrap(); + let request_elem = elem.clone(); + BlocklistRequest::try_from(request_elem).unwrap(); + + let result_elem = elem.clone(); + let result = BlocklistResult::try_from(result_elem).unwrap(); + assert_eq!(result.items, vec!()); + + let elem: Element = "".parse().unwrap(); + let block = Block::try_from(elem).unwrap(); + assert_eq!(block.items, vec!()); + + let elem: Element = "".parse().unwrap(); + let unblock = Unblock::try_from(elem).unwrap(); + assert_eq!(unblock.items, vec!()); + } + + #[test] + fn test_items() { + let elem: Element = "".parse().unwrap(); + let two_items = vec!( + Jid { + node: Some(String::from("coucou")), + domain: String::from("coucou"), + resource: None, + }, + Jid { + node: None, + domain: String::from("domain"), + resource: None, + }, + ); + + let request_elem = elem.clone(); + let error = BlocklistRequest::try_from(request_elem).unwrap_err(); + let message = match error { + Error::ParseError(string) => string, + _ => panic!(), + }; + assert_eq!(message, "Unknown child in blocklist element."); + + let result_elem = elem.clone(); + let result = BlocklistResult::try_from(result_elem).unwrap(); + assert_eq!(result.items, two_items); + + let elem: Element = "".parse().unwrap(); + let block = Block::try_from(elem).unwrap(); + assert_eq!(block.items, two_items); + + let elem: Element = "".parse().unwrap(); + let unblock = Unblock::try_from(elem).unwrap(); + assert_eq!(unblock.items, two_items); + } + + #[test] + fn test_invalid() { + let elem: Element = "".parse().unwrap(); + let request_elem = elem.clone(); + let error = BlocklistRequest::try_from(request_elem).unwrap_err(); + let message = match error { + Error::ParseError(string) => string, + _ => panic!(), + }; + assert_eq!(message, "Unknown attribute in blocklist element."); + + let result_elem = elem.clone(); + let error = BlocklistResult::try_from(result_elem).unwrap_err(); + let message = match error { + Error::ParseError(string) => string, + _ => panic!(), + }; + assert_eq!(message, "Unknown attribute in blocklist element."); + + let elem: Element = "".parse().unwrap(); + let error = Block::try_from(elem).unwrap_err(); + let message = match error { + Error::ParseError(string) => string, + _ => panic!(), + }; + assert_eq!(message, "Unknown attribute in block element."); + + let elem: Element = "".parse().unwrap(); + let error = Unblock::try_from(elem).unwrap_err(); + let message = match error { + Error::ParseError(string) => string, + _ => panic!(), + }; + assert_eq!(message, "Unknown attribute in unblock element."); + } +} diff --git a/src/lib.rs b/src/lib.rs index fee722cc..7eba6799 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -301,6 +301,9 @@ pub mod jingle; /// XEP-0184: Message Delivery Receipts pub mod receipts; +/// XEP-0191: Blocking Command +pub mod blocking; + /// XEP-0199: XMPP Ping pub mod ping; diff --git a/src/ns.rs b/src/ns.rs index 22e5f156..045957d5 100644 --- a/src/ns.rs +++ b/src/ns.rs @@ -62,6 +62,11 @@ pub const JINGLE: &str = "urn:xmpp:jingle:1"; /// XEP-0184: Message Delivery Receipts pub const RECEIPTS: &str = "urn:xmpp:receipts"; +/// XEP-0191: Blocking Command +pub const BLOCKING: &str = "urn:xmpp:blocking"; +/// XEP-0191: Blocking Command +pub const BLOCKING_ERRORS: &str = "urn:xmpp:blocking:errors"; + /// XEP-0199: XMPP Ping pub const PING: &str = "urn:xmpp:ping";