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