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