Implement serialization for structs with named fields
This commit is contained in:
parent
67c61e24dd
commit
99a7d561e0
|
@ -10,5 +10,6 @@ proc-macro = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
heck = "0.4"
|
heck = "0.4"
|
||||||
|
proc-macro2 = "1.0.39"
|
||||||
quote = "1.0.18"
|
quote = "1.0.18"
|
||||||
syn = { version = "1.0.86", features = ["full"] }
|
syn = { version = "1.0.86", features = ["full"] }
|
||||||
|
|
|
@ -6,15 +6,38 @@ use syn::parse_macro_input;
|
||||||
|
|
||||||
#[proc_macro_derive(ToXml)]
|
#[proc_macro_derive(ToXml)]
|
||||||
pub fn to_xml(input: TokenStream) -> TokenStream {
|
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 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() + "</" + #field_name + ">"));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
syn::Fields::Unnamed(_) => todo!(),
|
||||||
|
syn::Fields::Unit => {}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
_ => todo!(),
|
||||||
|
};
|
||||||
|
|
||||||
|
output.extend(quote!(+ "</" + #root_name + ">"));
|
||||||
|
|
||||||
TokenStream::from(quote!(
|
TokenStream::from(quote!(
|
||||||
impl ToXml for #ident {
|
impl ToXml for #ident {
|
||||||
fn write_xml<W: ::std::fmt::Write>(&self, write: &mut W) -> Result<(), instant_xml::Error> {
|
fn write_xml<W: ::std::fmt::Write>(&self, write: &mut W) -> Result<(), instant_xml::Error> {
|
||||||
write.write_str("<")?;
|
write.write_str(&(#output))?;
|
||||||
write.write_fmt(format_args!("{}", #name))?;
|
|
||||||
write.write_str("/>")?;
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,8 +3,29 @@ use instant_xml::{FromXml, ToXml};
|
||||||
#[derive(Debug, Eq, FromXml, PartialEq, ToXml)]
|
#[derive(Debug, Eq, FromXml, PartialEq, ToXml)]
|
||||||
struct Unit;
|
struct Unit;
|
||||||
|
|
||||||
|
#[derive(Debug, Eq, PartialEq, ToXml)]
|
||||||
|
struct StructWithNamedFields {
|
||||||
|
flag: bool,
|
||||||
|
string: String,
|
||||||
|
number: i32,
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn unit() {
|
fn unit() {
|
||||||
assert_eq!(Unit.to_xml().unwrap(), "<Unit/>");
|
assert_eq!(Unit.to_xml().unwrap(), "<Unit></Unit>");
|
||||||
assert_eq!(Unit::from_xml("<Unit/>").unwrap(), Unit);
|
assert_eq!(Unit::from_xml("<Unit/>").unwrap(), Unit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn struct_with_named_fields() {
|
||||||
|
assert_eq!(
|
||||||
|
StructWithNamedFields {
|
||||||
|
flag: true,
|
||||||
|
string: "test".to_string(),
|
||||||
|
number: 1,
|
||||||
|
}
|
||||||
|
.to_xml()
|
||||||
|
.unwrap(),
|
||||||
|
"<StructWithNamedFields><flag>true</flag><string>test</string><number>1</number></StructWithNamedFields>"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue