mod common; use common::init_logger; use serde::Deserialize; use serde_xml_rs::{from_str, Deserializer}; #[derive(Debug, Deserialize, PartialEq)] struct Item { name: String, source: String, } #[test] fn simple_struct_from_attributes() { init_logger(); let s = r##" "##; let item: Item = from_str(s).unwrap(); assert_eq!( item, Item { name: "hello".to_string(), source: "world.rs".to_string(), } ); } #[test] fn multiple_roots_attributes() { init_logger(); let s = r##" "##; let item: Vec = from_str(s).unwrap(); assert_eq!( item, vec![ Item { name: "hello".to_string(), source: "world.rs".to_string(), }, Item { name: "hello".to_string(), source: "world.rs".to_string(), }, ] ); } #[test] fn simple_struct_from_attribute_and_child() { init_logger(); let s = r##" world.rs "##; let item: Item = from_str(s).unwrap(); assert_eq!( item, Item { name: "hello".to_string(), source: "world.rs".to_string(), } ); } #[derive(Debug, Deserialize, PartialEq)] struct Project { name: String, #[serde(rename = "item", default)] items: Vec, } #[test] fn nested_collection() { init_logger(); let s = r##" "##; let project: Project = from_str(s).unwrap(); assert_eq!( project, Project { name: "my_project".to_string(), items: vec![ Item { name: "hello1".to_string(), source: "world1.rs".to_string(), }, Item { name: "hello2".to_string(), source: "world2.rs".to_string(), }, ], } ); } #[derive(Debug, Deserialize, PartialEq)] enum MyEnum { A(String), B { name: String, flag: bool }, C, } #[derive(Debug, Deserialize, PartialEq)] struct MyEnums { #[serde(rename = "$value")] items: Vec, } #[test] fn collection_of_enums() { init_logger(); let s = r##" test "##; let project: MyEnums = from_str(s).unwrap(); assert_eq!( project, MyEnums { items: vec![ MyEnum::A("test".to_string()), MyEnum::B { name: "hello".to_string(), flag: true, }, MyEnum::C, ], } ); } #[test] fn out_of_order_collection() { #[derive(Debug, Deserialize, PartialEq)] struct Collection { a: Vec, b: Vec, c: C, } #[derive(Debug, Deserialize, PartialEq)] struct A { name: String, } #[derive(Debug, Deserialize, PartialEq)] struct B { name: String, } #[derive(Debug, Deserialize, PartialEq)] struct C { name: String, } init_logger(); let in_xml = r#" "#; let should_be = Collection { a: vec![ A { name: "a1".into() }, A { name: "a2".into() }, A { name: "a3".into() }, A { name: "a4".into() }, ], b: vec![B { name: "b1".into() }, B { name: "b2".into() }], c: C { name: "c".into() }, }; let mut de = Deserializer::new_from_reader(in_xml.as_bytes()).non_contiguous_seq_elements(true); let actual = Collection::deserialize(&mut de).unwrap(); assert_eq!(should_be, actual); } #[test] fn nested_out_of_order_collection() { #[derive(Debug, Deserialize, PartialEq)] struct OuterCollection { a: A, inner: Vec, } #[derive(Debug, Deserialize, PartialEq)] struct InnerCollection { b: Vec, c: Vec, } #[derive(Debug, Deserialize, PartialEq)] struct A { name: String, } #[derive(Debug, Deserialize, PartialEq)] struct B { name: String, } #[derive(Debug, Deserialize, PartialEq)] struct C { name: String, } init_logger(); let in_xml = r#" "#; let should_be = OuterCollection { a: A { name: "a".into() }, inner: vec![ InnerCollection { b: vec![B { name: "b1".into() }, B { name: "b2".into() }], c: vec![C { name: "c1".into() }, C { name: "c2".into() }], }, InnerCollection { b: vec![B { name: "b3".into() }, B { name: "b4".into() }], c: vec![C { name: "c3".into() }, C { name: "c4".into() }], }, ], }; let mut de = Deserializer::new_from_reader(in_xml.as_bytes()).non_contiguous_seq_elements(true); let actual = OuterCollection::deserialize(&mut de).unwrap(); assert_eq!(should_be, actual); } #[test] fn out_of_order_tuple() { #[derive(Debug, Deserialize, PartialEq)] struct Collection { val: (A, B, C), other: A, } #[derive(Debug, Deserialize, PartialEq)] struct A { name_a: String, } #[derive(Debug, Deserialize, PartialEq)] struct B { name_b: String, } #[derive(Debug, Deserialize, PartialEq)] struct C { name_c: String, } init_logger(); let in_xml = r#" "#; let should_be = Collection { val: ( A { name_a: "a1".into(), }, B { name_b: "b".into() }, C { name_c: "c".into() }, ), other: A { name_a: "a2".into(), }, }; let mut de = Deserializer::new_from_reader(in_xml.as_bytes()).non_contiguous_seq_elements(true); let actual = Collection::deserialize(&mut de).unwrap(); assert_eq!(should_be, actual); } /// Ensure that identically-named elements at different depths are not deserialized as if they were /// at the same depth. #[test] fn nested_collection_repeated_elements() { #[derive(Debug, Deserialize, PartialEq)] struct OuterCollection { a: Vec, inner: Inner, } #[derive(Debug, Deserialize, PartialEq)] struct Inner { a: A, } #[derive(Debug, Deserialize, PartialEq)] struct A { name: String, } init_logger(); let in_xml = r#" "#; let should_be = OuterCollection { a: vec![A { name: "a1".into() }, A { name: "a3".into() }], inner: Inner { a: A { name: "a2".into() }, }, }; let mut de = Deserializer::new_from_reader(in_xml.as_bytes()).non_contiguous_seq_elements(true); let actual = OuterCollection::deserialize(&mut de).unwrap(); assert_eq!(should_be, actual); }