1use xso::{text::Base64, AsXml, FromXml};
8
9use crate::iq::IqSetPayload;
10use crate::ns;
11
12generate_id!(
13 StreamId
15);
16
17generate_attribute!(
18Stanza, "stanza", {
20 Iq => "iq",
24
25 Message => "message",
28}, Default = Iq);
29
30#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
32#[xml(namespace = ns::IBB, name = "open")]
33pub struct Open {
34 #[xml(attribute(name = "block-size"))]
36 pub block_size: u16,
37
38 #[xml(attribute)]
40 pub sid: StreamId,
41
42 #[xml(attribute(default))]
44 pub stanza: Stanza,
45}
46
47impl IqSetPayload for Open {}
48
49#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
51#[xml(namespace = ns::IBB, name = "data")]
52pub struct Data {
53 #[xml(attribute)]
55 pub seq: u16,
56
57 #[xml(attribute)]
59 pub sid: StreamId,
60
61 #[xml(text = Base64)]
63 pub data: Vec<u8>,
64}
65
66impl IqSetPayload for Data {}
67
68#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
70#[xml(namespace = ns::IBB, name = "close")]
71pub struct Close {
72 #[xml(attribute)]
74 pub sid: StreamId,
75}
76
77impl IqSetPayload for Close {}
78
79#[cfg(test)]
80mod tests {
81 use super::*;
82 use minidom::Element;
83 use xso::error::{Error, FromElementError};
84
85 #[cfg(target_pointer_width = "32")]
86 #[test]
87 fn test_size() {
88 assert_size!(StreamId, 12);
89 assert_size!(Stanza, 1);
90 assert_size!(Open, 16);
91 assert_size!(Data, 28);
92 assert_size!(Close, 12);
93 }
94
95 #[cfg(target_pointer_width = "64")]
96 #[test]
97 fn test_size() {
98 assert_size!(StreamId, 24);
99 assert_size!(Stanza, 1);
100 assert_size!(Open, 32);
101 assert_size!(Data, 56);
102 assert_size!(Close, 24);
103 }
104
105 #[test]
106 fn test_simple() {
107 let sid = StreamId(String::from("coucou"));
108
109 let elem: Element =
110 "<open xmlns='http://jabber.org/protocol/ibb' block-size='3' sid='coucou'/>"
111 .parse()
112 .unwrap();
113 let open = Open::try_from(elem).unwrap();
114 assert_eq!(open.block_size, 3);
115 assert_eq!(open.sid, sid);
116 assert_eq!(open.stanza, Stanza::Iq);
117
118 let elem: Element =
119 "<data xmlns='http://jabber.org/protocol/ibb' seq='0' sid='coucou'>AAAA</data>"
120 .parse()
121 .unwrap();
122 let data = Data::try_from(elem).unwrap();
123 assert_eq!(data.seq, 0);
124 assert_eq!(data.sid, sid);
125 assert_eq!(data.data, vec!(0, 0, 0));
126
127 let elem: Element = "<close xmlns='http://jabber.org/protocol/ibb' sid='coucou'/>"
128 .parse()
129 .unwrap();
130 let close = Close::try_from(elem).unwrap();
131 assert_eq!(close.sid, sid);
132 }
133
134 #[test]
135 fn test_invalid() {
136 let elem: Element = "<open xmlns='http://jabber.org/protocol/ibb'/>"
137 .parse()
138 .unwrap();
139 let error = Open::try_from(elem).unwrap_err();
140 let message = match error {
141 FromElementError::Invalid(Error::Other(string)) => string,
142 _ => panic!(),
143 };
144 assert_eq!(
145 message,
146 "Required attribute field 'block_size' on Open element missing."
147 );
148
149 let elem: Element = "<open xmlns='http://jabber.org/protocol/ibb' block-size='-5'/>"
150 .parse()
151 .unwrap();
152 let error = Open::try_from(elem).unwrap_err();
153 let message = match error {
154 FromElementError::Invalid(Error::TextParseError(error))
155 if error.is::<core::num::ParseIntError>() =>
156 {
157 error
158 }
159 _ => panic!(),
160 };
161 assert_eq!(message.to_string(), "invalid digit found in string");
162
163 let elem: Element = "<open xmlns='http://jabber.org/protocol/ibb' block-size='128'/>"
164 .parse()
165 .unwrap();
166 let error = Open::try_from(elem).unwrap_err();
167 let message = match error {
168 FromElementError::Invalid(Error::Other(error)) => error,
169 _ => panic!(),
170 };
171 assert_eq!(
172 message,
173 "Required attribute field 'sid' on Open element missing."
174 );
175 }
176
177 #[test]
178 fn test_invalid_stanza() {
179 let elem: Element = "<open xmlns='http://jabber.org/protocol/ibb' block-size='128' sid='coucou' stanza='fdsq'/>".parse().unwrap();
180 let error = Open::try_from(elem).unwrap_err();
181 let message = match error {
182 FromElementError::Invalid(Error::TextParseError(string)) => string,
183 _ => panic!(),
184 };
185 assert_eq!(message.to_string(), "Unknown value for 'stanza' attribute.");
186 }
187}