1 mod common;
2
3 use common::init_logger;
4 use serde::Deserialize;
5 use serde_xml_rs::{from_str, Deserializer};
6
7 #[derive(Debug, Deserialize, PartialEq)]
8 struct Item {
9 name: String,
10 source: String,
11 }
12
13 #[test]
simple_struct_from_attributes()14 fn simple_struct_from_attributes() {
15 init_logger();
16
17 let s = r##"
18 <item name="hello" source="world.rs" />
19 "##;
20
21 let item: Item = from_str(s).unwrap();
22
23 assert_eq!(
24 item,
25 Item {
26 name: "hello".to_string(),
27 source: "world.rs".to_string(),
28 }
29 );
30 }
31
32 #[test]
multiple_roots_attributes()33 fn multiple_roots_attributes() {
34 init_logger();
35
36 let s = r##"
37 <item name="hello" source="world.rs" />
38 <item name="hello" source="world.rs" />
39 "##;
40
41 let item: Vec<Item> = from_str(s).unwrap();
42
43 assert_eq!(
44 item,
45 vec![
46 Item {
47 name: "hello".to_string(),
48 source: "world.rs".to_string(),
49 },
50 Item {
51 name: "hello".to_string(),
52 source: "world.rs".to_string(),
53 },
54 ]
55 );
56 }
57
58 #[test]
simple_struct_from_attribute_and_child()59 fn simple_struct_from_attribute_and_child() {
60 init_logger();
61
62 let s = r##"
63 <item name="hello">
64 <source>world.rs</source>
65 </item>
66 "##;
67
68 let item: Item = from_str(s).unwrap();
69
70 assert_eq!(
71 item,
72 Item {
73 name: "hello".to_string(),
74 source: "world.rs".to_string(),
75 }
76 );
77 }
78
79 #[derive(Debug, Deserialize, PartialEq)]
80 struct Project {
81 name: String,
82
83 #[serde(rename = "item", default)]
84 items: Vec<Item>,
85 }
86
87 #[test]
nested_collection()88 fn nested_collection() {
89 init_logger();
90
91 let s = r##"
92 <project name="my_project">
93 <item name="hello1" source="world1.rs" />
94 <item name="hello2" source="world2.rs" />
95 </project>
96 "##;
97
98 let project: Project = from_str(s).unwrap();
99
100 assert_eq!(
101 project,
102 Project {
103 name: "my_project".to_string(),
104 items: vec![
105 Item {
106 name: "hello1".to_string(),
107 source: "world1.rs".to_string(),
108 },
109 Item {
110 name: "hello2".to_string(),
111 source: "world2.rs".to_string(),
112 },
113 ],
114 }
115 );
116 }
117
118 #[derive(Debug, Deserialize, PartialEq)]
119 enum MyEnum {
120 A(String),
121 B { name: String, flag: bool },
122 C,
123 }
124
125 #[derive(Debug, Deserialize, PartialEq)]
126 struct MyEnums {
127 #[serde(rename = "$value")]
128 items: Vec<MyEnum>,
129 }
130
131 #[test]
collection_of_enums()132 fn collection_of_enums() {
133 init_logger();
134
135 let s = r##"
136 <enums>
137 <A>test</A>
138 <B name="hello" flag="true" />
139 <C />
140 </enums>
141 "##;
142
143 let project: MyEnums = from_str(s).unwrap();
144
145 assert_eq!(
146 project,
147 MyEnums {
148 items: vec![
149 MyEnum::A("test".to_string()),
150 MyEnum::B {
151 name: "hello".to_string(),
152 flag: true,
153 },
154 MyEnum::C,
155 ],
156 }
157 );
158 }
159
160 #[test]
out_of_order_collection()161 fn out_of_order_collection() {
162 #[derive(Debug, Deserialize, PartialEq)]
163 struct Collection {
164 a: Vec<A>,
165 b: Vec<B>,
166 c: C,
167 }
168
169 #[derive(Debug, Deserialize, PartialEq)]
170 struct A {
171 name: String,
172 }
173
174 #[derive(Debug, Deserialize, PartialEq)]
175 struct B {
176 name: String,
177 }
178
179 #[derive(Debug, Deserialize, PartialEq)]
180 struct C {
181 name: String,
182 }
183
184 init_logger();
185
186 let in_xml = r#"
187 <collection>
188 <a name="a1" />
189 <a name="a2" />
190 <b name="b1" />
191 <a name="a3" />
192 <c name="c" />
193 <b name="b2" />
194 <a name="a4" />
195 </collection>
196 "#;
197
198 let should_be = Collection {
199 a: vec![
200 A { name: "a1".into() },
201 A { name: "a2".into() },
202 A { name: "a3".into() },
203 A { name: "a4".into() },
204 ],
205 b: vec![B { name: "b1".into() }, B { name: "b2".into() }],
206 c: C { name: "c".into() },
207 };
208
209 let mut de = Deserializer::new_from_reader(in_xml.as_bytes()).non_contiguous_seq_elements(true);
210 let actual = Collection::deserialize(&mut de).unwrap();
211
212 assert_eq!(should_be, actual);
213 }
214
215 #[test]
nested_out_of_order_collection()216 fn nested_out_of_order_collection() {
217 #[derive(Debug, Deserialize, PartialEq)]
218 struct OuterCollection {
219 a: A,
220 inner: Vec<InnerCollection>,
221 }
222
223 #[derive(Debug, Deserialize, PartialEq)]
224 struct InnerCollection {
225 b: Vec<B>,
226 c: Vec<C>,
227 }
228
229 #[derive(Debug, Deserialize, PartialEq)]
230 struct A {
231 name: String,
232 }
233
234 #[derive(Debug, Deserialize, PartialEq)]
235 struct B {
236 name: String,
237 }
238
239 #[derive(Debug, Deserialize, PartialEq)]
240 struct C {
241 name: String,
242 }
243
244 init_logger();
245
246 let in_xml = r#"
247 <collection>
248 <inner>
249 <b name="b1" />
250 <c name="c1" />
251 <b name="b2" />
252 <c name="c2" />
253 </inner>
254 <a name="a" />
255 <inner>
256 <c name="c3" />
257 <b name="b3" />
258 <c name="c4" />
259 <b name="b4" />
260 </inner>
261 </collection>
262 "#;
263
264 let should_be = OuterCollection {
265 a: A { name: "a".into() },
266 inner: vec![
267 InnerCollection {
268 b: vec![B { name: "b1".into() }, B { name: "b2".into() }],
269 c: vec![C { name: "c1".into() }, C { name: "c2".into() }],
270 },
271 InnerCollection {
272 b: vec![B { name: "b3".into() }, B { name: "b4".into() }],
273 c: vec![C { name: "c3".into() }, C { name: "c4".into() }],
274 },
275 ],
276 };
277
278 let mut de = Deserializer::new_from_reader(in_xml.as_bytes()).non_contiguous_seq_elements(true);
279 let actual = OuterCollection::deserialize(&mut de).unwrap();
280
281 assert_eq!(should_be, actual);
282 }
283
284 #[test]
out_of_order_tuple()285 fn out_of_order_tuple() {
286 #[derive(Debug, Deserialize, PartialEq)]
287 struct Collection {
288 val: (A, B, C),
289 other: A,
290 }
291
292 #[derive(Debug, Deserialize, PartialEq)]
293 struct A {
294 name_a: String,
295 }
296
297 #[derive(Debug, Deserialize, PartialEq)]
298 struct B {
299 name_b: String,
300 }
301
302 #[derive(Debug, Deserialize, PartialEq)]
303 struct C {
304 name_c: String,
305 }
306
307 init_logger();
308
309 let in_xml = r#"
310 <collection>
311 <val name_a="a1" />
312 <val name_b="b" />
313 <other name_a="a2" />
314 <val name_c="c" />
315 </collection>
316 "#;
317
318 let should_be = Collection {
319 val: (
320 A {
321 name_a: "a1".into(),
322 },
323 B { name_b: "b".into() },
324 C { name_c: "c".into() },
325 ),
326 other: A {
327 name_a: "a2".into(),
328 },
329 };
330
331 let mut de = Deserializer::new_from_reader(in_xml.as_bytes()).non_contiguous_seq_elements(true);
332 let actual = Collection::deserialize(&mut de).unwrap();
333
334 assert_eq!(should_be, actual);
335 }
336
337 /// Ensure that identically-named elements at different depths are not deserialized as if they were
338 /// at the same depth.
339 #[test]
nested_collection_repeated_elements()340 fn nested_collection_repeated_elements() {
341 #[derive(Debug, Deserialize, PartialEq)]
342 struct OuterCollection {
343 a: Vec<A>,
344 inner: Inner,
345 }
346
347 #[derive(Debug, Deserialize, PartialEq)]
348 struct Inner {
349 a: A,
350 }
351
352 #[derive(Debug, Deserialize, PartialEq)]
353 struct A {
354 name: String,
355 }
356
357 init_logger();
358
359 let in_xml = r#"
360 <collection>
361 <a name="a1" />
362 <inner>
363 <a name="a2" />
364 </inner>
365 <a name="a3" />
366 </collection>
367 "#;
368
369 let should_be = OuterCollection {
370 a: vec![A { name: "a1".into() }, A { name: "a3".into() }],
371 inner: Inner {
372 a: A { name: "a2".into() },
373 },
374 };
375
376 let mut de = Deserializer::new_from_reader(in_xml.as_bytes()).non_contiguous_seq_elements(true);
377 let actual = OuterCollection::deserialize(&mut de).unwrap();
378
379 assert_eq!(should_be, actual);
380 }
381