diff --git a/instant-xml-macros/Cargo.toml b/instant-xml-macros/Cargo.toml index d92fd9e..b37ea5a 100644 --- a/instant-xml-macros/Cargo.toml +++ b/instant-xml-macros/Cargo.toml @@ -10,5 +10,6 @@ proc-macro = true [dependencies] heck = "0.4" +proc-macro2 = "1.0.39" quote = "1.0.18" syn = { version = "1.0.86", features = ["full"] } diff --git a/instant-xml-macros/src/lib.rs b/instant-xml-macros/src/lib.rs index a47580e..adc333f 100644 --- a/instant-xml-macros/src/lib.rs +++ b/instant-xml-macros/src/lib.rs @@ -6,15 +6,38 @@ use syn::parse_macro_input; #[proc_macro_derive(ToXml)] pub fn to_xml(input: TokenStream) -> TokenStream { - let ast = parse_macro_input!(input as syn::ItemStruct); + let ast = parse_macro_input!(input as syn::DeriveInput); let ident = &ast.ident; - let name = ident.to_string(); + let root_name = ident.to_string(); + let mut output: proc_macro2::TokenStream = + TokenStream::from(quote!("<".to_owned() + #root_name + ">")).into(); + + match &ast.data { + syn::Data::Struct(ref data) => { + match data.fields { + syn::Fields::Named(ref fields) => { + fields + .named + .iter() + .for_each(|field| { + let field_name = field.ident.as_ref().unwrap().to_string(); + let field_value = field.ident.as_ref().unwrap(); + output.extend(quote!(+ "<" + #field_name + ">" + self.#field_value.to_string().as_str() + "")); + }); + } + syn::Fields::Unnamed(_) => todo!(), + syn::Fields::Unit => {} + }; + } + _ => todo!(), + }; + + output.extend(quote!(+ "")); + TokenStream::from(quote!( impl ToXml for #ident { fn write_xml(&self, write: &mut W) -> Result<(), instant_xml::Error> { - write.write_str("<")?; - write.write_fmt(format_args!("{}", #name))?; - write.write_str("/>")?; + write.write_str(&(#output))?; Ok(()) } } diff --git a/instant-xml/tests/all.rs b/instant-xml/tests/all.rs index b159bc5..d552a19 100644 --- a/instant-xml/tests/all.rs +++ b/instant-xml/tests/all.rs @@ -3,8 +3,29 @@ use instant_xml::{FromXml, ToXml}; #[derive(Debug, Eq, FromXml, PartialEq, ToXml)] struct Unit; +#[derive(Debug, Eq, PartialEq, ToXml)] +struct StructWithNamedFields { + flag: bool, + string: String, + number: i32, +} + #[test] fn unit() { - assert_eq!(Unit.to_xml().unwrap(), ""); + assert_eq!(Unit.to_xml().unwrap(), ""); assert_eq!(Unit::from_xml("").unwrap(), Unit); } + +#[test] +fn struct_with_named_fields() { + assert_eq!( + StructWithNamedFields { + flag: true, + string: "test".to_string(), + number: 1, + } + .to_xml() + .unwrap(), + "truetest1" + ); +}