1use crate::data_forms::DataForm;
8use crate::iq::{IqGetPayload, IqResultPayload, IqSetPayload};
9use crate::ns;
10use alloc::collections::BTreeMap;
11use minidom::Element;
12use xso::error::{Error, FromElementError};
13
14#[derive(Debug, Clone)]
16pub struct Query {
17 pub fields: BTreeMap<String, String>,
20
21 pub registered: bool,
23
24 pub remove: bool,
26
27 pub form: Option<DataForm>,
29 }
32
33impl IqGetPayload for Query {}
34impl IqSetPayload for Query {}
35impl IqResultPayload for Query {}
36
37impl TryFrom<Element> for Query {
38 type Error = FromElementError;
39
40 fn try_from(elem: Element) -> Result<Query, FromElementError> {
41 check_self!(elem, "query", REGISTER, "IBR query");
42 let mut query = Query {
43 registered: false,
44 fields: BTreeMap::new(),
45 remove: false,
46 form: None,
47 };
48 for child in elem.children() {
49 let namespace = child.ns();
50 if namespace == ns::REGISTER {
51 let name = child.name();
52 let fields = vec![
53 "address",
54 "city",
55 "date",
56 "email",
57 "first",
58 "instructions",
59 "key",
60 "last",
61 "misc",
62 "name",
63 "nick",
64 "password",
65 "phone",
66 "state",
67 "text",
68 "url",
69 "username",
70 "zip",
71 ];
72 if fields.binary_search(&name).is_ok() {
73 query.fields.insert(name.to_owned(), child.text());
74 } else if name == "registered" {
75 query.registered = true;
76 } else if name == "remove" {
77 query.remove = true;
78 } else {
79 return Err(Error::Other("Wrong field in ibr element.").into());
80 }
81 } else if child.is("x", ns::DATA_FORMS) {
82 query.form = Some(DataForm::try_from(child.clone())?);
83 } else {
84 return Err(Error::Other("Unknown child in ibr element.").into());
85 }
86 }
87 Ok(query)
88 }
89}
90
91impl From<Query> for Element {
92 fn from(query: Query) -> Element {
93 Element::builder("query", ns::REGISTER)
94 .append_all(if query.registered {
95 Some(Element::builder("registered", ns::REGISTER))
96 } else {
97 None
98 })
99 .append_all(
100 query
101 .fields
102 .into_iter()
103 .map(|(name, value)| Element::builder(name, ns::REGISTER).append(value)),
104 )
105 .append_all(if query.remove {
106 Some(Element::builder("remove", ns::REGISTER))
107 } else {
108 None
109 })
110 .append_all(query.form.map(Element::from))
111 .build()
112 }
113}
114
115#[cfg(test)]
116mod tests {
117 use super::*;
118
119 #[cfg(target_pointer_width = "32")]
120 #[test]
121 fn test_size() {
122 assert_size!(Query, 68);
123 }
124
125 #[cfg(target_pointer_width = "64")]
126 #[test]
127 fn test_size() {
128 assert_size!(Query, 136);
129 }
130
131 #[test]
132 fn test_simple() {
133 let elem: Element = "<query xmlns='jabber:iq:register'/>".parse().unwrap();
134 Query::try_from(elem).unwrap();
135 }
136
137 #[test]
138 fn test_ex2() {
139 let elem: Element = r#"<query xmlns='jabber:iq:register'>
140 <instructions>
141 Choose a username and password for use with this service.
142 Please also provide your email address.
143 </instructions>
144 <username/>
145 <password/>
146 <email/>
147</query>
148"#
149 .parse()
150 .unwrap();
151 let query = Query::try_from(elem).unwrap();
152 assert_eq!(query.registered, false);
153 assert_eq!(query.fields["instructions"], "\n Choose a username and password for use with this service.\n Please also provide your email address.\n ");
154 assert_eq!(query.fields["username"], "");
155 assert_eq!(query.fields["password"], "");
156 assert_eq!(query.fields["email"], "");
157 assert_eq!(query.fields.contains_key("name"), false);
158
159 }
163
164 #[test]
165 fn test_ex9() {
166 let elem: Element = "<query xmlns='jabber:iq:register'><instructions>Use the enclosed form to register. If your Jabber client does not support Data Forms, visit http://www.shakespeare.lit/contests.php</instructions><x xmlns='jabber:x:data' type='form'><title>Contest Registration</title><instructions>Please provide the following information to sign up for our special contests!</instructions><field type='hidden' var='FORM_TYPE'><value>jabber:iq:register</value></field><field label='Given Name' var='first'><required/></field><field label='Family Name' var='last'><required/></field><field label='Email Address' var='email'><required/></field><field type='list-single' label='Gender' var='x-gender'><option label='Male'><value>M</value></option><option label='Female'><value>F</value></option></field></x></query>"
167 .parse()
168 .unwrap();
169 let elem1 = elem.clone();
170 let query = Query::try_from(elem).unwrap();
171 assert_eq!(query.registered, false);
172 assert!(!query.fields["instructions"].is_empty());
173 let form = query.form.clone().unwrap();
174 assert!(!form.instructions.unwrap().is_empty());
175 let elem2 = query.into();
176 assert_eq!(elem1, elem2);
177 }
178
179 #[test]
180 fn test_ex10() {
181 let elem: Element = "<query xmlns='jabber:iq:register'><x xmlns='jabber:x:data' type='submit'><field type='hidden' var='FORM_TYPE'><value>jabber:iq:register</value></field><field label='Given Name' var='first'><value>Juliet</value></field><field label='Family Name' var='last'><value>Capulet</value></field><field label='Email Address' var='email'><value>juliet@capulet.com</value></field><field type='list-single' label='Gender' var='x-gender'><value>F</value></field></x></query>"
182 .parse()
183 .unwrap();
184 let elem1 = elem.clone();
185 let query = Query::try_from(elem).unwrap();
186 assert_eq!(query.registered, false);
187 for _ in &query.fields {
188 panic!();
189 }
190 let elem2 = query.into();
191 assert_eq!(elem1, elem2);
192 }
193}