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}