diff --git a/examples/Cargo.toml b/examples/Cargo.toml index 35c130b..269a727 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -8,4 +8,5 @@ description = "Examples for YaSerDe project" documentation = "https://docs.rs/yaserde" [dependencies] +xml = "0.8.20" yaserde = {version = "0.10.1", path = "../yaserde", features = ["yaserde_derive"] } diff --git a/examples/src/custom_serializer_ab.rs b/examples/src/custom_serializer_ab.rs new file mode 100644 index 0000000..cfebbdd --- /dev/null +++ b/examples/src/custom_serializer_ab.rs @@ -0,0 +1,262 @@ +use yaserde::{YaDeserialize, YaSerialize}; + +#[derive(Debug, PartialEq, YaDeserialize)] +struct RootElem { + children: Vec, +} +impl YaSerialize for RootElem { + fn serialize( + &self, + writer: &mut yaserde::ser::Serializer, + ) -> Result<(), String> { + writer.write("Root {\n").unwrap(); + writer.write("/* A|B elements */\n").unwrap(); + for e in &self.children { + e.serialize(writer).unwrap(); + } + writer.write("}\n").unwrap(); + Ok(()) + } + + fn serialize_attributes( + &self, + attributes: Vec, + namespace: xml::namespace::Namespace, + ) -> Result< + ( + Vec, + xml::namespace::Namespace, + ), + String, + > { + Ok((attributes, namespace)) + } +} + +#[derive(Debug, PartialEq)] +// #[derive(YaDeserialize)] +// #[yaserde(rename = "a")] +struct A { + // #[yaserde(attribute)] + attr: String, +} +impl YaSerialize for A { + fn serialize( + &self, + writer: &mut yaserde::ser::Serializer, + ) -> Result<(), String> { + writer.write("A {").unwrap(); + writer + .write(format!("attr: {:?},", self.attr.as_str()).as_str()) + .unwrap(); + writer.write("}\n").unwrap(); + Ok(()) + } + + fn serialize_attributes( + &self, + attributes: Vec, + namespace: xml::namespace::Namespace, + ) -> Result< + ( + Vec, + xml::namespace::Namespace, + ), + String, + > { + Ok((attributes, namespace)) + } +} + +#[derive(Debug, PartialEq)] +// #[derive(YaDeserialize)] +// #[yaserde(rename = "b")] +struct B {} +impl YaSerialize for B { + fn serialize( + &self, + writer: &mut yaserde::ser::Serializer, + ) -> Result<(), String> { + writer.write("B {}\n").unwrap(); + Ok(()) + } + + fn serialize_attributes( + &self, + attributes: Vec, + namespace: xml::namespace::Namespace, + ) -> Result< + ( + Vec, + xml::namespace::Namespace, + ), + String, + > { + Ok((attributes, namespace)) + } +} + +#[derive(Debug, PartialEq)] +// #[derive(Default)] +enum AB { + // #[default] + // None, + A(A), + B(B), +} +impl Default for AB { + fn default() -> Self { + // NOTE: for debugging only; will be None + Self::A(A { + attr: String::from("undefined"), + }) + } +} +impl YaDeserialize for AB { + fn deserialize( + reader: &mut yaserde::de::Deserializer, + ) -> Result { + // dispatch to YaDeserialize for element + print!(" - - - - -DISPATCHING"); + if let xml::reader::XmlEvent::StartElement { name, .. } = reader.peek()?.to_owned() { + match name.local_name.as_str() { + "a" => { + let deserialized = A { attr: String::from("NOT DESERIALIZED")}; // TODO: A::deserialize(reader)?; + return Ok(Self::A(deserialized)); + } + "b" => { + let deserialized = B {}; // TODO: B::deserialize(reader)?; + return Ok(Self::B(deserialized)); + } + _ => (), + } + } + Err(format!("Expected a StartElement")) + } +} +impl YaSerialize for AB { + fn serialize( + &self, + writer: &mut yaserde::ser::Serializer, + ) -> Result<(), String> { + writer.write("/* serialized AB */\n").unwrap(); + match self { + // Self::None => { + // writer.write("UndefinedAB").unwrap(); + // // return Err(format!("None element cannot be serialized")); + // } + Self::A(a) => { + a.serialize(writer).unwrap(); + } + Self::B(b) => { + b.serialize(writer).unwrap(); + } + } + writer.write("}\n").unwrap(); + Ok(()) + } + + fn serialize_attributes( + &self, + attributes: Vec, + namespace: xml::namespace::Namespace, + ) -> Result< + ( + Vec, + xml::namespace::Namespace, + ), + String, + > { + Ok((attributes, namespace)) + } +} + +#[test] +#[ignore = "TODO: fully support Rust enums (allow multiple XML element occurences and create a Vec)"] +fn serialize_ab() { + use std::fs; + + let content = + fs::read_to_string("tests/data/ab.xml").expect("something went wrong reading the file"); + let loaded: RootElem = yaserde::de::from_str(&content).unwrap(); + println!("{:?}", &loaded); + let yaserde_conf = yaserde::ser::Config { + indent_string: Some(String::from(" ")), + perform_indent: true, + write_document_declaration: false, + }; + let result = yaserde::ser::to_string_with_config(&loaded, &yaserde_conf).unwrap(); + println!("\n\nSerialized output:\n{:?}", &result); + + let reference = RootElem { + // ab: AB::default(), + children: vec![ + AB::A(A { + attr: String::from("hallo 1"), + }), + AB::B(B {}), + AB::A(A { + attr: String::from("hallo 2"), + }), + AB::B(B {}), + AB::A(A { + attr: String::from("hallo 3"), + }), + AB::B(B {}), + AB::B(B {}), + AB::B(B {}), + AB::B(B {}), + AB::A(A { + attr: String::from("hallo 4"), + }), + AB::B(B {}), + ], + // a_children: vec![ + // A { + // attr: String::from("hallo 1"), + // }, + // A { + // attr: String::from("hallo 2"), + // }, + // A { + // attr: String::from("hallo 3"), + // }, + // A { + // attr: String::from("hallo 4"), + // }, + // ], + // b_children: vec![B {}, B {}, B {}, B {}, B {}, B {}, B {}], + }; + assert_eq!(&loaded, &reference); + + assert_eq!( + &result, + r##"Root { +/* A|B elements */ +A{attr = "hallo 1"} +B{} +A{attr = "hallo 2"} +B{} +A{attr = "hallo 3"} +B{} +B{} +B{} +B{} +A{attr = "hallo 4"} +B{} +/* only A elements */ +A{attr = "hallo 1"} +A{attr = "hallo 2"} +A{attr = "hallo 3"} +A{attr = "hallo 4"} +/* only B elements */ +B{} +B{} +B{} +B{} +B{} +B{} +B{} +}"##, + ) +} diff --git a/examples/src/lib.rs b/examples/src/lib.rs index 8f83b28..bc09428 100644 --- a/examples/src/lib.rs +++ b/examples/src/lib.rs @@ -1,5 +1,6 @@ mod bbigras_namespace; mod boscop; +mod custom_serializer_ab; mod generic; mod ln_dom; mod svd; diff --git a/examples/tests/data/ab.xml b/examples/tests/data/ab.xml new file mode 100644 index 0000000..6a26af5 --- /dev/null +++ b/examples/tests/data/ab.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + +