blocking.rs

  1// Copyright (c) 2017 Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
  2//
  3// This Source Code Form is subject to the terms of the Mozilla Public
  4// License, v. 2.0. If a copy of the MPL was not distributed with this
  5// file, You can obtain one at http://mozilla.org/MPL/2.0/.
  6
  7use try_from::TryFrom;
  8
  9use jid::Jid;
 10use minidom::Element;
 11
 12use error::Error;
 13
 14use ns;
 15
 16generate_empty_element!(BlocklistRequest, "blocklist", ns::BLOCKING);
 17
 18fn get_children_items(elem: Element) -> Result<Vec<Jid>, Error> {
 19    let mut items = vec!();
 20    for child in elem.children() {
 21        check_self!(child, "item", ns::BLOCKING);
 22        check_no_unknown_attributes!(child, "item", ["jid"]);
 23        check_no_children!(child, "item");
 24        items.push(get_attr!(child, "jid", required));
 25    }
 26    Ok(items)
 27}
 28
 29macro_rules! generate_blocking_element {
 30    ($elem:ident, $name:tt) => (
 31        #[derive(Debug, Clone)]
 32        pub struct $elem {
 33            pub items: Vec<Jid>,
 34        }
 35
 36        impl TryFrom<Element> for $elem {
 37            type Err = Error;
 38
 39            fn try_from(elem: Element) -> Result<$elem, Error> {
 40                check_self!(elem, $name, ns::BLOCKING);
 41                check_no_attributes!(elem, $name);
 42                Ok($elem {
 43                    items: get_children_items(elem)?,
 44                })
 45            }
 46        }
 47
 48        impl From<$elem> for Element {
 49            fn from(elem: $elem) -> Element {
 50                Element::builder($name)
 51                        .ns(ns::BLOCKING)
 52                        .append(elem.items.into_iter().map(|jid| {
 53                             Element::builder("item")
 54                                     .ns(ns::BLOCKING)
 55                                     .attr("jid", jid)
 56                                     .build()
 57                         }).collect::<Vec<_>>())
 58                        .build()
 59            }
 60        }
 61    );
 62}
 63
 64generate_blocking_element!(BlocklistResult, "blocklist");
 65generate_blocking_element!(Block, "block");
 66generate_blocking_element!(Unblock, "unblock");
 67
 68generate_empty_element!(Blocked, "blocked", ns::BLOCKING_ERRORS);
 69
 70#[cfg(test)]
 71mod tests {
 72    use super::*;
 73
 74    #[test]
 75    fn test_simple() {
 76        let elem: Element = "<blocklist xmlns='urn:xmpp:blocking'/>".parse().unwrap();
 77        let request_elem = elem.clone();
 78        BlocklistRequest::try_from(request_elem).unwrap();
 79
 80        let result_elem = elem.clone();
 81        let result = BlocklistResult::try_from(result_elem).unwrap();
 82        assert_eq!(result.items, vec!());
 83
 84        let elem: Element = "<block xmlns='urn:xmpp:blocking'/>".parse().unwrap();
 85        let block = Block::try_from(elem).unwrap();
 86        assert_eq!(block.items, vec!());
 87
 88        let elem: Element = "<unblock xmlns='urn:xmpp:blocking'/>".parse().unwrap();
 89        let unblock = Unblock::try_from(elem).unwrap();
 90        assert_eq!(unblock.items, vec!());
 91    }
 92
 93    #[test]
 94    fn test_items() {
 95        let elem: Element = "<blocklist xmlns='urn:xmpp:blocking'><item jid='coucou@coucou'/><item jid='domain'/></blocklist>".parse().unwrap();
 96        let two_items = vec!(
 97            Jid {
 98                node: Some(String::from("coucou")),
 99                domain: String::from("coucou"),
100                resource: None,
101            },
102            Jid {
103                node: None,
104                domain: String::from("domain"),
105                resource: None,
106            },
107        );
108
109        let request_elem = elem.clone();
110        let error = BlocklistRequest::try_from(request_elem).unwrap_err();
111        let message = match error {
112            Error::ParseError(string) => string,
113            _ => panic!(),
114        };
115        assert_eq!(message, "Unknown child in blocklist element.");
116
117        let result_elem = elem.clone();
118        let result = BlocklistResult::try_from(result_elem).unwrap();
119        assert_eq!(result.items, two_items);
120
121        let elem: Element = "<block xmlns='urn:xmpp:blocking'><item jid='coucou@coucou'/><item jid='domain'/></block>".parse().unwrap();
122        let block = Block::try_from(elem).unwrap();
123        assert_eq!(block.items, two_items);
124
125        let elem: Element = "<unblock xmlns='urn:xmpp:blocking'><item jid='coucou@coucou'/><item jid='domain'/></unblock>".parse().unwrap();
126        let unblock = Unblock::try_from(elem).unwrap();
127        assert_eq!(unblock.items, two_items);
128    }
129
130    #[test]
131    fn test_invalid() {
132        let elem: Element = "<blocklist xmlns='urn:xmpp:blocking' coucou=''/>".parse().unwrap();
133        let request_elem = elem.clone();
134        let error = BlocklistRequest::try_from(request_elem).unwrap_err();
135        let message = match error {
136            Error::ParseError(string) => string,
137            _ => panic!(),
138        };
139        assert_eq!(message, "Unknown attribute in blocklist element.");
140
141        let result_elem = elem.clone();
142        let error = BlocklistResult::try_from(result_elem).unwrap_err();
143        let message = match error {
144            Error::ParseError(string) => string,
145            _ => panic!(),
146        };
147        assert_eq!(message, "Unknown attribute in blocklist element.");
148
149        let elem: Element = "<block xmlns='urn:xmpp:blocking' coucou=''/>".parse().unwrap();
150        let error = Block::try_from(elem).unwrap_err();
151        let message = match error {
152            Error::ParseError(string) => string,
153            _ => panic!(),
154        };
155        assert_eq!(message, "Unknown attribute in block element.");
156
157        let elem: Element = "<unblock xmlns='urn:xmpp:blocking' coucou=''/>".parse().unwrap();
158        let error = Unblock::try_from(elem).unwrap_err();
159        let message = match error {
160            Error::ParseError(string) => string,
161            _ => panic!(),
162        };
163        assert_eq!(message, "Unknown attribute in unblock element.");
164    }
165}