use syn; use quote; pub fn build(ast: &syn::DeriveInput) -> quote::Tokens { let fields = match ast.body { syn::Body::Enum(_) => panic!("Deriving DnsTextData not supported for enum types"), syn::Body::Struct(syn::VariantData::Struct(ref s)) => s, syn::Body::Struct(_) => panic!("Deriving DnsTextData not supported for unit / tuple struct types"), }; if !ast.generics.ty_params.is_empty() { panic!("Type parameters not supported for deriving DnsTextData"); } if !ast.generics.where_clause.predicates.is_empty() { panic!("Where clauses not supported for deriving DnsTextData"); } if !ast.generics.lifetimes.is_empty() { panic!("Lifetimes not supported for deriving DnsTextData"); } let name = &ast.ident; let mut parse_fields = quote!{}; let mut format_fields = quote!{}; for field in fields { let field_name = field.ident.as_ref().unwrap(); parse_fields = quote!{#parse_fields #field_name: DnsTextData::dns_parse(_context, _data).with_context(|_| format!("failed parsing field {}::{}", stringify!(#name), stringify!(#field_name)))?, }; format_fields = quote!{#format_fields DnsTextData::dns_format(&self.#field_name, f)?; }; } quote!{ #[allow(unused_imports)] impl ::dnsbox_base::ser::DnsTextData for #name { fn dns_parse(_context: &::dnsbox_base::ser::text::DnsTextContext, _data: &mut &str) -> ::dnsbox_base::errors::Result { use dnsbox_base::failure::ResultExt; use dnsbox_base::ser::DnsTextData; Ok(#name{ #parse_fields }) } fn dns_format(&self, f: &mut ::dnsbox_base::ser::text::DnsTextFormatter) -> ::std::fmt::Result { use dnsbox_base::ser::DnsTextData; use std::fmt::{self, Write}; #format_fields Ok(()) } } } }