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", BLOCKING);
17
18macro_rules! generate_blocking_element {
19 ($elem:ident, $name:tt) => (
20 #[derive(Debug, Clone)]
21 pub struct $elem {
22 pub items: Vec<Jid>,
23 }
24
25 impl TryFrom<Element> for $elem {
26 type Err = Error;
27
28 fn try_from(elem: Element) -> Result<$elem, Error> {
29 check_self!(elem, $name, BLOCKING);
30 check_no_attributes!(elem, $name);
31 let mut items = vec!();
32 for child in elem.children() {
33 check_self!(child, "item", BLOCKING);
34 check_no_unknown_attributes!(child, "item", ["jid"]);
35 check_no_children!(child, "item");
36 items.push(get_attr!(child, "jid", required));
37 }
38 Ok($elem { items })
39 }
40 }
41
42 impl From<$elem> for Element {
43 fn from(elem: $elem) -> Element {
44 Element::builder($name)
45 .ns(ns::BLOCKING)
46 .append(elem.items.into_iter().map(|jid| {
47 Element::builder("item")
48 .ns(ns::BLOCKING)
49 .attr("jid", jid)
50 .build()
51 }).collect::<Vec<_>>())
52 .build()
53 }
54 }
55 );
56}
57
58generate_blocking_element!(BlocklistResult, "blocklist");
59generate_blocking_element!(Block, "block");
60generate_blocking_element!(Unblock, "unblock");
61
62generate_empty_element!(Blocked, "blocked", BLOCKING_ERRORS);
63
64#[cfg(test)]
65mod tests {
66 use super::*;
67
68 #[test]
69 fn test_simple() {
70 let elem: Element = "<blocklist xmlns='urn:xmpp:blocking'/>".parse().unwrap();
71 let request_elem = elem.clone();
72 BlocklistRequest::try_from(request_elem).unwrap();
73
74 let result_elem = elem.clone();
75 let result = BlocklistResult::try_from(result_elem).unwrap();
76 assert_eq!(result.items, vec!());
77
78 let elem: Element = "<block xmlns='urn:xmpp:blocking'/>".parse().unwrap();
79 let block = Block::try_from(elem).unwrap();
80 assert_eq!(block.items, vec!());
81
82 let elem: Element = "<unblock xmlns='urn:xmpp:blocking'/>".parse().unwrap();
83 let unblock = Unblock::try_from(elem).unwrap();
84 assert_eq!(unblock.items, vec!());
85 }
86
87 #[test]
88 fn test_items() {
89 let elem: Element = "<blocklist xmlns='urn:xmpp:blocking'><item jid='coucou@coucou'/><item jid='domain'/></blocklist>".parse().unwrap();
90 let two_items = vec!(
91 Jid {
92 node: Some(String::from("coucou")),
93 domain: String::from("coucou"),
94 resource: None,
95 },
96 Jid {
97 node: None,
98 domain: String::from("domain"),
99 resource: None,
100 },
101 );
102
103 let request_elem = elem.clone();
104 let error = BlocklistRequest::try_from(request_elem).unwrap_err();
105 let message = match error {
106 Error::ParseError(string) => string,
107 _ => panic!(),
108 };
109 assert_eq!(message, "Unknown child in blocklist element.");
110
111 let result_elem = elem.clone();
112 let result = BlocklistResult::try_from(result_elem).unwrap();
113 assert_eq!(result.items, two_items);
114
115 let elem: Element = "<block xmlns='urn:xmpp:blocking'><item jid='coucou@coucou'/><item jid='domain'/></block>".parse().unwrap();
116 let block = Block::try_from(elem).unwrap();
117 assert_eq!(block.items, two_items);
118
119 let elem: Element = "<unblock xmlns='urn:xmpp:blocking'><item jid='coucou@coucou'/><item jid='domain'/></unblock>".parse().unwrap();
120 let unblock = Unblock::try_from(elem).unwrap();
121 assert_eq!(unblock.items, two_items);
122 }
123
124 #[test]
125 fn test_invalid() {
126 let elem: Element = "<blocklist xmlns='urn:xmpp:blocking' coucou=''/>".parse().unwrap();
127 let request_elem = elem.clone();
128 let error = BlocklistRequest::try_from(request_elem).unwrap_err();
129 let message = match error {
130 Error::ParseError(string) => string,
131 _ => panic!(),
132 };
133 assert_eq!(message, "Unknown attribute in blocklist element.");
134
135 let result_elem = elem.clone();
136 let error = BlocklistResult::try_from(result_elem).unwrap_err();
137 let message = match error {
138 Error::ParseError(string) => string,
139 _ => panic!(),
140 };
141 assert_eq!(message, "Unknown attribute in blocklist element.");
142
143 let elem: Element = "<block xmlns='urn:xmpp:blocking' coucou=''/>".parse().unwrap();
144 let error = Block::try_from(elem).unwrap_err();
145 let message = match error {
146 Error::ParseError(string) => string,
147 _ => panic!(),
148 };
149 assert_eq!(message, "Unknown attribute in block element.");
150
151 let elem: Element = "<unblock xmlns='urn:xmpp:blocking' coucou=''/>".parse().unwrap();
152 let error = Unblock::try_from(elem).unwrap_err();
153 let message = match error {
154 Error::ParseError(string) => string,
155 _ => panic!(),
156 };
157 assert_eq!(message, "Unknown attribute in unblock element.");
158 }
159}