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