use xml::reader::XmlEvent as ReadEvent; use xml::writer::XmlEvent as WriteEvent; use yaserde::{ser, YaDeserialize as YaDeserializeTrait, YaSerialize as YaSerializeTrait}; #[derive(Debug, PartialEq, Default)] pub struct MaybeString { field_name: String, content: Option, } impl YaDeserializeTrait for MaybeString { fn deserialize( reader: &mut yaserde::de::Deserializer, ) -> Result { let field_name = match reader.peek()? { ReadEvent::StartElement { name, attributes, .. } => { if attributes.len() > 0 { return Err(String::from( "Attributes not currently supported by MaybeString", )); } name.local_name.clone() } _ => return Err(String::from("Unsupporte ReadEvent type")), }; reader.next_event()?; let content = match reader.peek()? { ReadEvent::Characters(content) => Some(content.clone()), ReadEvent::EndElement { name } => { if name.local_name != field_name { return Err(format!( "Invalid EndElement, expected {field_name} but got {}", name.local_name )); } None } _ => return Err(String::from("Unsupporte ReadEvent type")), }; Ok(Self { field_name, content, }) } } impl YaSerializeTrait for MaybeString { fn serialize(&self, writer: &mut ser::Serializer) -> Result<(), String> { let start_element_event = WriteEvent::start_element(self.field_name.as_str()); writer.write(start_element_event).expect("Writer failed"); match &self.content { Some(content) => { writer .write(WriteEvent::characters(content)) .expect("Writer failed"); } None => {} }; writer .write(WriteEvent::end_element()) .expect("Writer failed"); Ok(()) } fn serialize_attributes( &self, _attributes: Vec, _namespace: xml::namespace::Namespace, ) -> Result< ( Vec, xml::namespace::Namespace, ), String, > { unimplemented!("MaybeString does not currently support attributes") } } #[cfg(test)] mod test { use super::*; use pretty_assertions::assert_eq; use yaserde_derive::YaDeserialize; use yaserde_derive::YaSerialize; #[derive(Debug, PartialEq, Default, YaDeserialize, YaSerialize)] struct TestStruct { maybe: MaybeString, } #[test] fn maybe_string_should_deserialize_empty_element() { let initial_xml = ""; let test_struct: TestStruct = yaserde::de::from_str(initial_xml).expect("Shoudl deserialize teststruct"); println!("Got test_struct {:?}", test_struct); assert_eq!( test_struct, TestStruct { maybe: MaybeString { field_name: String::from("maybe"), content: None } } ); } #[test] fn maybe_string_should_deserialize_content() { let initial_xml = "some content"; let test_struct: TestStruct = yaserde::de::from_str(initial_xml).expect("Shoudl deserialize teststruct"); println!("Got test_struct {:?}", test_struct); assert_eq!( test_struct, TestStruct { maybe: MaybeString { field_name: String::from("maybe"), content: Some(String::from("some content")) } } ); } #[test] fn maybe_string_should_deserialize_empty_long_format() { let initial_xml = ""; let test_struct: TestStruct = yaserde::de::from_str(initial_xml).expect("Shoudl deserialize teststruct"); println!("Got test_struct {:?}", test_struct); assert_eq!( test_struct, TestStruct { maybe: MaybeString { field_name: String::from("maybe"), content: None } } ); } #[test] fn maybe_string_should_serialize_to_empty_element() { let initial_xml = r#""#; let test_struct: TestStruct = yaserde::de::from_str(initial_xml).expect("Shoudl deserialize teststruct"); println!("Got test_struct {:?}", test_struct); assert_eq!( yaserde::ser::to_string(&test_struct).expect("should serialize teststruct"), initial_xml ); } #[test] fn maybe_string_should_serialize_content() { let initial_xml = r#"some content"#; let test_struct: TestStruct = yaserde::de::from_str(initial_xml).expect("Shoudl deserialize teststruct"); println!("Got test_struct {:?}", test_struct); assert_eq!( yaserde::ser::to_string(&test_struct).expect("should serialize teststruct"), initial_xml ); } }