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