1use xso::{AsXml, FromXml};
8
9use crate::ns;
10use crate::stanza_error::DefinedCondition;
11
12#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
14#[xml(namespace = ns::SM, name = "a")]
15pub struct A {
16 #[xml(attribute)]
18 pub h: u32,
19}
20
21impl A {
22 pub fn new(h: u32) -> A {
24 A { h }
25 }
26}
27
28#[derive(FromXml, AsXml, PartialEq, Debug, Clone, Default)]
30#[xml(namespace = ns::SM, name = "enable")]
31pub struct Enable {
32 #[xml(attribute(default))]
35 pub max: Option<u32>,
36
37 #[xml(attribute(default))]
39 pub resume: bool,
40}
41
42impl Enable {
43 pub fn new() -> Self {
45 Enable::default()
46 }
47
48 pub fn with_max(mut self, max: u32) -> Self {
50 self.max = Some(max);
51 self
52 }
53
54 pub fn with_resume(mut self) -> Self {
56 self.resume = true;
57 self
58 }
59}
60
61generate_id!(
62 StreamId
64);
65
66#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
68#[xml(namespace = ns::SM, name = "enabled")]
69pub struct Enabled {
70 #[xml(attribute(default))]
72 pub id: Option<StreamId>,
73
74 #[xml(attribute(default))]
77 pub location: Option<String>,
78
79 #[xml(attribute(default))]
82 pub max: Option<u32>,
83
84 #[xml(attribute(default))]
86 pub resume: bool,
87}
88
89#[derive(FromXml, AsXml, Debug, PartialEq, Clone)]
91#[xml(namespace = ns::SM, name = "failed")]
92pub struct Failed {
93 #[xml(attribute)]
95 pub h: Option<u32>,
96
97 #[xml(child(default))]
100 pub error: Option<DefinedCondition>,
101}
102
103#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
105#[xml(namespace = ns::SM, name = "r")]
106pub struct R;
107
108#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
110#[xml(namespace = ns::SM, name = "resume")]
111pub struct Resume {
112 #[xml(attribute)]
114 pub h: u32,
115
116 #[xml(attribute)]
119 pub previd: StreamId,
120}
121
122#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
124#[xml(namespace = ns::SM, name = "resumed")]
125pub struct Resumed {
126 #[xml(attribute)]
128 pub h: u32,
129
130 #[xml(attribute)]
133 pub previd: StreamId,
134}
135
136#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
139#[xml(namespace = ns::SM, name = "sm")]
140pub struct StreamManagement {
141 #[xml(flag)]
143 pub optional: bool,
144
145 #[xml(flag)]
147 pub required: bool,
148}
149
150#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
153#[xml(namespace = ns::SM, name = "handled-count-too-high")]
154pub struct HandledCountTooHigh {
155 #[xml(attribute)]
157 pub h: u32,
158
159 #[xml(attribute = "send-count")]
161 pub send_count: u32,
162}
163
164impl From<HandledCountTooHigh> for crate::stream_error::StreamError {
165 fn from(other: HandledCountTooHigh) -> Self {
166 Self {
167 condition: crate::stream_error::DefinedCondition::UndefinedCondition,
168 text: Some((
169 None,
170 format!(
171 "You acknowledged {} stanza(s), while I only sent {} so far.",
172 other.h, other.send_count
173 ),
174 )),
175 application_specific: vec![other.into()],
176 }
177 }
178}
179
180#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
182#[xml()]
183pub enum Nonza {
184 #[xml(transparent)]
186 Enable(Enable),
187
188 #[xml(transparent)]
190 Enabled(Enabled),
191
192 #[xml(transparent)]
194 Resume(Resume),
195
196 #[xml(transparent)]
198 Resumed(Resumed),
199
200 #[xml(transparent)]
202 Failed(Failed),
203
204 #[xml(transparent)]
206 Ack(A),
207
208 #[xml(transparent)]
210 Req(R),
211}
212
213#[cfg(test)]
214mod tests {
215 use super::*;
216 use minidom::Element;
217
218 #[cfg(target_pointer_width = "32")]
219 #[test]
220 fn test_size() {
221 assert_size!(A, 4);
222 assert_size!(Enable, 12);
223 assert_size!(StreamId, 12);
224 assert_size!(Enabled, 36);
225 assert_size!(Failed, 24);
226 assert_size!(R, 0);
227 assert_size!(Resume, 16);
228 assert_size!(Resumed, 16);
229 assert_size!(StreamManagement, 2);
230 assert_size!(HandledCountTooHigh, 8);
231 }
232
233 #[cfg(target_pointer_width = "64")]
234 #[test]
235 fn test_size() {
236 assert_size!(A, 4);
237 assert_size!(Enable, 12);
238 assert_size!(StreamId, 24);
239 assert_size!(Enabled, 64);
240 assert_size!(Failed, 40);
241 assert_size!(R, 0);
242 assert_size!(Resume, 32);
243 assert_size!(Resumed, 32);
244 assert_size!(StreamManagement, 2);
245 assert_size!(HandledCountTooHigh, 8);
246 }
247
248 #[test]
249 fn a() {
250 let elem: Element = "<a xmlns='urn:xmpp:sm:3' h='5'/>".parse().unwrap();
251 let a = A::try_from(elem).unwrap();
252 assert_eq!(a.h, 5);
253 }
254
255 #[test]
256 fn stream_feature() {
257 let elem: Element = "<sm xmlns='urn:xmpp:sm:3'/>".parse().unwrap();
258 let sm = StreamManagement::try_from(elem).unwrap();
259 assert_eq!(sm.optional, false);
260 assert_eq!(sm.required, false);
261 }
262
263 #[test]
264 fn handle_count_too_high() {
265 let elem: Element = "<handled-count-too-high xmlns='urn:xmpp:sm:3' h='10' send-count='8'/>"
266 .parse()
267 .unwrap();
268 let elem = HandledCountTooHigh::try_from(elem).unwrap();
269 assert_eq!(elem.h, 10);
270 assert_eq!(elem.send_count, 8);
271 }
272
273 #[test]
274 fn resume() {
275 let elem: Element = "<enable xmlns='urn:xmpp:sm:3' resume='true'/>"
276 .parse()
277 .unwrap();
278 let enable = Enable::try_from(elem).unwrap();
279 assert_eq!(enable.max, None);
280 assert_eq!(enable.resume, true);
281
282 let elem: Element = "<enabled xmlns='urn:xmpp:sm:3' resume='true' id='coucou' max='600'/>"
283 .parse()
284 .unwrap();
285 let enabled = Enabled::try_from(elem).unwrap();
286 let previd = enabled.id.unwrap();
287 assert_eq!(enabled.resume, true);
288 assert_eq!(previd, StreamId(String::from("coucou")));
289 assert_eq!(enabled.max, Some(600));
290 assert_eq!(enabled.location, None);
291
292 let elem: Element = "<resume xmlns='urn:xmpp:sm:3' h='5' previd='coucou'/>"
293 .parse()
294 .unwrap();
295 let resume = Resume::try_from(elem).unwrap();
296 assert_eq!(resume.h, 5);
297 assert_eq!(resume.previd, previd);
298
299 let elem: Element = "<resumed xmlns='urn:xmpp:sm:3' h='5' previd='coucou'/>"
300 .parse()
301 .unwrap();
302 let resumed = Resumed::try_from(elem).unwrap();
303 assert_eq!(resumed.h, 5);
304 assert_eq!(resumed.previd, previd);
305 }
306
307 #[test]
308 fn test_serialize_failed() {
309 let reference: Element = "<failed xmlns='urn:xmpp:sm:3'><unexpected-request xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/></failed>"
310 .parse()
311 .unwrap();
312
313 let elem: Element = "<unexpected-request xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>"
314 .parse()
315 .unwrap();
316
317 let error = DefinedCondition::try_from(elem).unwrap();
318
319 let failed = Failed {
320 h: None,
321 error: Some(error),
322 };
323 let serialized: Element = failed.into();
324 assert_eq!(serialized, reference);
325 }
326}