1use xso::{AsXml, FromXml};
8
9use crate::mam;
10use crate::ns;
11use minidom::Element;
12
13#[derive(FromXml, AsXml, Debug, Clone, PartialEq)]
16#[xml(namespace = ns::BIND2, name = "bind")]
17pub struct BindFeature {
18 #[xml(extract(default, name = "inline", fields(extract(n = .., name = "feature", fields(attribute(name = "var", type_ = String))))))]
20 pub inline_features: Vec<String>,
21}
22
23#[derive(FromXml, AsXml, Debug, Clone, PartialEq)]
26#[xml(namespace = ns::BIND2, name = "bind")]
27pub struct BindQuery {
28 #[xml(extract(default, fields(text(type_ = String))))]
32 pub tag: Option<String>,
33
34 #[xml(element(n = ..))]
36 pub payloads: Vec<Element>,
37}
38
39#[derive(FromXml, AsXml, Debug, Clone, PartialEq)]
42#[xml(namespace = ns::BIND2, name = "bound")]
43pub struct Bound {
44 #[xml(child(default))]
47 pub mam_metadata: Option<mam::MetadataResponse>,
48
49 #[xml(element(n = ..))]
51 pub payloads: Vec<Element>,
52}
53
54#[cfg(test)]
55mod tests {
56 use super::*;
57
58 #[cfg(target_pointer_width = "32")]
59 #[test]
60 fn test_size() {
61 assert_size!(BindFeature, 12);
62 assert_size!(BindQuery, 24);
63 assert_size!(Bound, 68);
64 }
65
66 #[cfg(target_pointer_width = "64")]
67 #[test]
68 fn test_size() {
69 assert_size!(BindFeature, 24);
70 assert_size!(BindQuery, 48);
71 assert_size!(Bound, 104);
72 }
73
74 #[test]
75 fn test_empty() {
76 let elem: Element = "<bind xmlns='urn:xmpp:bind:0'/>".parse().unwrap();
77 let bind = BindQuery::try_from(elem).unwrap();
78 assert_eq!(bind.tag, None);
79 assert_eq!(bind.payloads.len(), 0);
80 }
81
82 #[test]
83 fn test_simple() {
84 let elem: Element =
86 "<bind xmlns='urn:xmpp:bind:0'><inline><feature var='urn:xmpp:carbons:2'/><feature var='urn:xmpp:csi:0'/><feature var='urn:xmpp:sm:3'/></inline></bind>"
87 .parse()
88 .unwrap();
89 let bind = BindFeature::try_from(elem.clone()).unwrap();
90 assert_eq!(bind.inline_features.len(), 3);
91 assert_eq!(bind.inline_features[0], "urn:xmpp:carbons:2");
92 assert_eq!(bind.inline_features[1], "urn:xmpp:csi:0");
93 assert_eq!(bind.inline_features[2], "urn:xmpp:sm:3");
94 let elem2 = bind.into();
95 assert_eq!(elem, elem2);
96
97 let elem: Element = "<bind xmlns='urn:xmpp:bind:0'><tag>AwesomeXMPP</tag></bind>"
99 .parse()
100 .unwrap();
101 let bind = BindQuery::try_from(elem).unwrap();
102 assert_eq!(bind.tag.unwrap(), "AwesomeXMPP");
103 assert_eq!(bind.payloads.len(), 0);
104
105 let elem: Element = "<bind xmlns='urn:xmpp:bind:0'><tag>AwesomeXMPP</tag><enable xmlns='urn:xmpp:carbons:2'/><enable xmlns='urn:xmpp:sm:3'/><inactive xmlns='urn:xmpp:csi:0'/></bind>".parse().unwrap();
107 let bind = BindQuery::try_from(elem).unwrap();
108 assert_eq!(bind.tag.unwrap(), "AwesomeXMPP");
109 assert_eq!(bind.payloads.len(), 3);
110
111 let elem: Element = "<bound xmlns='urn:xmpp:bind:0'><metadata xmlns='urn:xmpp:mam:2'><start id='YWxwaGEg' timestamp='2008-08-22T21:09:04Z'/><end id='b21lZ2Eg' timestamp='2020-04-20T14:34:21Z'/></metadata></bound>".parse().unwrap();
113 let bound = Bound::try_from(elem).unwrap();
114 assert!(bound.mam_metadata.is_some());
115 assert_eq!(bound.payloads.len(), 0);
116 }
117}