use syn; use quote; pub fn build(ast: &syn::DeriveInput) -> quote::Tokens { let fields = match ast.body { syn::Body::Enum(_) => panic!("Deriving DnsPacketData not supported for enum types"), syn::Body::Struct(syn::VariantData::Struct(ref s)) => s, syn::Body::Struct(_) => panic!("Deriving DnsPacketData not supported for unit / tuple struct types"), }; if !ast.generics.ty_params.is_empty() { panic!("Type parameters not supported for deriving DnsPacketData"); } if !ast.generics.where_clause.predicates.is_empty() { panic!("Where clauses not supported for deriving DnsPacketData"); } if !ast.generics.lifetimes.is_empty() { panic!("Lifetimes not supported for deriving DnsPacketData"); } let name = &ast.ident; let mut parse_fields = quote!{}; for field in fields { let field_name = field.ident.as_ref().unwrap(); let ctx_msg = format!("failed parsing field {}::{}", name, field_name); parse_fields = quote!{#parse_fields #field_name: DnsPacketData::deserialize(_data).context(#ctx_msg)?, }; } quote!{ impl ::dnsbox_base::ser::DnsPacketData for #name { #[allow(unused_imports)] fn deserialize(_data: &mut ::std::io::Cursor<::dnsbox_base::bytes::Bytes>) -> ::dnsbox_base::errors::Result { use ::dnsbox_base::failure::ResultExt; use ::dnsbox_base::ser::DnsPacketData; Ok(#name{ #parse_fields }) } } } }