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
146#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
149#[xml(namespace = ns::SM, name = "handled-count-too-high")]
150pub struct HandledCountTooHigh {
151 #[xml(attribute)]
153 pub h: u32,
154
155 #[xml(attribute = "send-count")]
157 pub send_count: u32,
158}
159
160impl From<HandledCountTooHigh> for crate::stream_error::StreamError {
161 fn from(other: HandledCountTooHigh) -> Self {
162 Self {
163 condition: crate::stream_error::DefinedCondition::UndefinedCondition,
164 text: Some((
165 None,
166 format!(
167 "You acknowledged {} stanza(s), while I only sent {} so far.",
168 other.h, other.send_count
169 ),
170 )),
171 application_specific: vec![other.into()],
172 }
173 }
174}
175
176#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
178#[xml()]
179pub enum Nonza {
180 #[xml(transparent)]
182 Enable(Enable),
183
184 #[xml(transparent)]
186 Enabled(Enabled),
187
188 #[xml(transparent)]
190 Resume(Resume),
191
192 #[xml(transparent)]
194 Resumed(Resumed),
195
196 #[xml(transparent)]
198 Failed(Failed),
199
200 #[xml(transparent)]
202 Ack(A),
203
204 #[xml(transparent)]
206 Req(R),
207}
208
209#[cfg(test)]
210mod tests {
211 use super::*;
212 use minidom::Element;
213
214 #[cfg(target_pointer_width = "32")]
215 #[test]
216 fn test_size() {
217 assert_size!(A, 4);
218 assert_size!(Enable, 12);
219 assert_size!(StreamId, 12);
220 assert_size!(Enabled, 36);
221 assert_size!(Failed, 24);
222 assert_size!(R, 0);
223 assert_size!(Resume, 16);
224 assert_size!(Resumed, 16);
225 assert_size!(StreamManagement, 1);
226 assert_size!(HandledCountTooHigh, 8);
227 }
228
229 #[cfg(target_pointer_width = "64")]
230 #[test]
231 fn test_size() {
232 assert_size!(A, 4);
233 assert_size!(Enable, 12);
234 assert_size!(StreamId, 24);
235 assert_size!(Enabled, 64);
236 assert_size!(Failed, 40);
237 assert_size!(R, 0);
238 assert_size!(Resume, 32);
239 assert_size!(Resumed, 32);
240 assert_size!(StreamManagement, 1);
241 assert_size!(HandledCountTooHigh, 8);
242 }
243
244 #[test]
245 fn a() {
246 let elem: Element = "<a xmlns='urn:xmpp:sm:3' h='5'/>".parse().unwrap();
247 let a = A::try_from(elem).unwrap();
248 assert_eq!(a.h, 5);
249 }
250
251 #[test]
252 fn stream_feature() {
253 let elem: Element = "<sm xmlns='urn:xmpp:sm:3'/>".parse().unwrap();
254 StreamManagement::try_from(elem).unwrap();
255 }
256
257 #[test]
258 fn handle_count_too_high() {
259 let elem: Element = "<handled-count-too-high xmlns='urn:xmpp:sm:3' h='10' send-count='8'/>"
260 .parse()
261 .unwrap();
262 let elem = HandledCountTooHigh::try_from(elem).unwrap();
263 assert_eq!(elem.h, 10);
264 assert_eq!(elem.send_count, 8);
265 }
266
267 #[test]
268 fn resume() {
269 let elem: Element = "<enable xmlns='urn:xmpp:sm:3' resume='true'/>"
270 .parse()
271 .unwrap();
272 let enable = Enable::try_from(elem).unwrap();
273 assert_eq!(enable.max, None);
274 assert_eq!(enable.resume, true);
275
276 let elem: Element = "<enabled xmlns='urn:xmpp:sm:3' resume='true' id='coucou' max='600'/>"
277 .parse()
278 .unwrap();
279 let enabled = Enabled::try_from(elem).unwrap();
280 let previd = enabled.id.unwrap();
281 assert_eq!(enabled.resume, true);
282 assert_eq!(previd, StreamId(String::from("coucou")));
283 assert_eq!(enabled.max, Some(600));
284 assert_eq!(enabled.location, None);
285
286 let elem: Element = "<resume xmlns='urn:xmpp:sm:3' h='5' previd='coucou'/>"
287 .parse()
288 .unwrap();
289 let resume = Resume::try_from(elem).unwrap();
290 assert_eq!(resume.h, 5);
291 assert_eq!(resume.previd, previd);
292
293 let elem: Element = "<resumed xmlns='urn:xmpp:sm:3' h='5' previd='coucou'/>"
294 .parse()
295 .unwrap();
296 let resumed = Resumed::try_from(elem).unwrap();
297 assert_eq!(resumed.h, 5);
298 assert_eq!(resumed.previd, previd);
299 }
300
301 #[test]
302 fn test_serialize_failed() {
303 let reference: Element = "<failed xmlns='urn:xmpp:sm:3'><unexpected-request xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/></failed>"
304 .parse()
305 .unwrap();
306
307 let elem: Element = "<unexpected-request xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>"
308 .parse()
309 .unwrap();
310
311 let error = DefinedCondition::try_from(elem).unwrap();
312
313 let failed = Failed {
314 h: None,
315 error: Some(error),
316 };
317 let serialized: Element = failed.into();
318 assert_eq!(serialized, reference);
319 }
320}