2022-08-11 10:26:45 +00:00
|
|
|
use proc_macro2::TokenStream;
|
2022-09-05 11:28:52 +00:00
|
|
|
use quote::quote;
|
2022-08-11 10:26:45 +00:00
|
|
|
|
2022-09-07 09:14:41 +00:00
|
|
|
use super::{discard_lifetimes, ContainerMeta, FieldMeta};
|
2022-08-11 10:26:45 +00:00
|
|
|
|
2022-09-05 11:14:31 +00:00
|
|
|
pub fn to_xml(input: &syn::DeriveInput) -> proc_macro2::TokenStream {
|
|
|
|
let mut body = TokenStream::new();
|
|
|
|
let mut attributes = TokenStream::new();
|
2022-09-07 07:53:11 +00:00
|
|
|
let meta = ContainerMeta::from_derive(input);
|
2022-09-05 11:14:31 +00:00
|
|
|
match &input.data {
|
|
|
|
syn::Data::Struct(ref data) => {
|
|
|
|
match data.fields {
|
|
|
|
syn::Fields::Named(ref fields) => {
|
|
|
|
fields.named.iter().for_each(|field| {
|
2022-09-07 07:53:11 +00:00
|
|
|
process_named_field(field, &mut body, &mut attributes, &meta);
|
2022-09-05 11:14:31 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
syn::Fields::Unnamed(_) => todo!(),
|
|
|
|
syn::Fields::Unit => {}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
_ => todo!(),
|
|
|
|
};
|
|
|
|
|
2022-09-07 10:00:31 +00:00
|
|
|
let default_namespace = match &meta.ns.uri {
|
|
|
|
Some(ns) => quote!(#ns),
|
|
|
|
None => quote!(""),
|
|
|
|
};
|
2022-09-07 07:53:11 +00:00
|
|
|
|
2022-09-07 10:00:31 +00:00
|
|
|
let cx_len = meta.ns.prefixes.len();
|
|
|
|
let mut context = quote!(
|
|
|
|
let mut new = ::instant_xml::ser::Context::<#cx_len>::default();
|
|
|
|
new.default_ns = #default_namespace;
|
|
|
|
);
|
|
|
|
for (i, (prefix, ns)) in meta.ns.prefixes.iter().enumerate() {
|
|
|
|
context.extend(quote!(
|
|
|
|
new.prefixes[#i] = ::instant_xml::ser::Prefix { ns: #ns, prefix: #prefix };
|
2022-09-07 07:53:11 +00:00
|
|
|
));
|
|
|
|
}
|
2022-09-05 11:14:31 +00:00
|
|
|
|
2022-09-07 07:53:11 +00:00
|
|
|
let ident = &input.ident;
|
|
|
|
let root_name = ident.to_string();
|
|
|
|
let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
|
2022-09-05 11:14:31 +00:00
|
|
|
|
|
|
|
quote!(
|
2022-09-05 11:28:52 +00:00
|
|
|
impl #impl_generics ToXml for #ident #ty_generics #where_clause {
|
2022-09-05 11:14:31 +00:00
|
|
|
fn serialize<W: ::core::fmt::Write + ?::core::marker::Sized>(
|
|
|
|
&self,
|
|
|
|
serializer: &mut instant_xml::Serializer<W>,
|
|
|
|
) -> Result<(), instant_xml::Error> {
|
2022-09-07 07:53:11 +00:00
|
|
|
// Start tag
|
2022-09-07 10:00:31 +00:00
|
|
|
match serializer.default_ns() == #default_namespace {
|
2022-09-07 09:14:41 +00:00
|
|
|
true => serializer.write_start(None, #root_name, None)?,
|
|
|
|
false => serializer.write_start(None, #root_name, Some(#default_namespace))?,
|
2022-09-07 07:53:11 +00:00
|
|
|
}
|
|
|
|
|
2022-09-07 10:00:31 +00:00
|
|
|
#context
|
|
|
|
let old = serializer.push(new)?;
|
|
|
|
|
2022-09-05 11:14:31 +00:00
|
|
|
#attributes
|
2022-09-07 09:14:41 +00:00
|
|
|
serializer.end_start()?;
|
2022-09-05 11:14:31 +00:00
|
|
|
|
|
|
|
#body
|
2022-09-07 07:53:11 +00:00
|
|
|
|
|
|
|
// Close tag
|
2022-09-07 09:14:41 +00:00
|
|
|
serializer.write_close(None, #root_name)?;
|
2022-09-07 10:00:31 +00:00
|
|
|
serializer.pop(old);
|
2022-09-05 11:14:31 +00:00
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
2022-09-07 09:14:41 +00:00
|
|
|
|
|
|
|
const KIND: ::instant_xml::Kind = ::instant_xml::Kind::Element(::instant_xml::Id {
|
|
|
|
ns: #default_namespace,
|
|
|
|
name: #root_name,
|
|
|
|
});
|
2022-09-05 11:14:31 +00:00
|
|
|
};
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2022-09-07 07:53:11 +00:00
|
|
|
fn process_named_field(
|
|
|
|
field: &syn::Field,
|
|
|
|
body: &mut TokenStream,
|
|
|
|
attributes: &mut TokenStream,
|
|
|
|
meta: &ContainerMeta,
|
|
|
|
) {
|
|
|
|
let name = field.ident.as_ref().unwrap().to_string();
|
|
|
|
let field_value = field.ident.as_ref().unwrap();
|
|
|
|
|
|
|
|
let field_meta = FieldMeta::from_field(field);
|
|
|
|
if field_meta.attribute {
|
|
|
|
attributes.extend(quote!(
|
2022-09-07 09:14:41 +00:00
|
|
|
serializer.write_attr(#name, &self.#field_value)?;
|
2022-08-11 10:26:45 +00:00
|
|
|
));
|
2022-09-07 07:53:11 +00:00
|
|
|
return;
|
2022-08-11 10:26:45 +00:00
|
|
|
}
|
2022-08-31 15:03:01 +00:00
|
|
|
|
2022-09-07 07:53:11 +00:00
|
|
|
let ns = match field_meta.ns.uri {
|
|
|
|
Some(ns) => quote!(#ns),
|
|
|
|
None => match &meta.ns.uri {
|
|
|
|
Some(ns) => quote!(#ns),
|
|
|
|
None => quote!(""),
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
2022-09-07 09:14:41 +00:00
|
|
|
let mut no_lifetime_type = field.ty.clone();
|
|
|
|
discard_lifetimes(&mut no_lifetime_type);
|
2022-09-07 07:53:11 +00:00
|
|
|
body.extend(quote!(
|
2022-09-07 09:14:41 +00:00
|
|
|
match <#no_lifetime_type as ToXml>::KIND {
|
|
|
|
::instant_xml::Kind::Element(_) => {
|
|
|
|
self.#field_value.serialize(serializer)?;
|
|
|
|
}
|
|
|
|
::instant_xml::Kind::Scalar => {
|
2022-09-07 10:00:31 +00:00
|
|
|
let (prefix, ns) = match serializer.default_ns() == #ns {
|
2022-09-07 09:14:41 +00:00
|
|
|
true => (None, None),
|
2022-09-07 10:00:31 +00:00
|
|
|
false => match serializer.prefix(#ns) {
|
|
|
|
Some(prefix) => (Some(prefix), None),
|
2022-09-07 09:14:41 +00:00
|
|
|
None => (None, Some(#ns)),
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
serializer.write_start(prefix, #name, ns)?;
|
|
|
|
serializer.end_start()?;
|
|
|
|
self.#field_value.serialize(serializer)?;
|
|
|
|
serializer.write_close(prefix, #name)?;
|
|
|
|
}
|
2022-08-31 15:03:01 +00:00
|
|
|
}
|
2022-09-07 07:53:11 +00:00
|
|
|
));
|
2022-08-11 10:26:45 +00:00
|
|
|
}
|