use syn; use quote; use super::{attr_get_single_list_arg}; #[derive(Clone,Debug)] enum StructAttribute { RRTypeName(quote::Tokens), } struct StructAttributeParser<'a>(pub &'a [syn::Attribute]); impl<'a> Iterator for StructAttributeParser<'a> { type Item = StructAttribute; fn next(&mut self) -> Option { while !self.0.is_empty() { let a = &self.0[0]; self.0 = &self.0[1..]; if a.is_sugared_doc { continue; } match a.value.name() { "RRTypeName" => { return Some(StructAttribute::RRTypeName(attr_get_single_list_arg(a))); }, _ => (), } } None } } pub fn build(ast: &syn::DeriveInput) -> quote::Tokens { if !ast.generics.ty_params.is_empty() { panic!("Type parameters not supported for deriving RRData"); } if !ast.generics.where_clause.predicates.is_empty() { panic!("Where clauses not supported for deriving RRData"); } if !ast.generics.lifetimes.is_empty() { panic!("Lifetimes not supported for deriving RRData"); } let name = &ast.ident; let mut name_str = { let name_str: &str = name.as_ref(); quote!{#name_str} }; for attr in StructAttributeParser(&ast.attrs) { match attr { StructAttribute::RRTypeName(name) => { name_str = name; }, } } let test_mod_name = syn::Ident::from(format!("test_rr_{}", name)); quote!{ impl ::dnsbox_base::ser::RRData for #name { fn rr_type(&self) -> ::dnsbox_base::common_types::Type { ::dnsbox_base::common_types::types::#name } } impl ::dnsbox_base::ser::StaticRRData for #name { const TYPE: ::dnsbox_base::common_types::Type = ::dnsbox_base::common_types::types::#name; const NAME: &'static str = #name_str; } // #[cfg(test)] #[allow(non_snake_case, unused_imports)] mod #test_mod_name { use dnsbox_base::records::registry; use dnsbox_base::common_types::types; use dnsbox_base::ser::StaticRRData; #[test] fn test_registry() { assert_eq!( registry::known_name_to_type(#name::NAME), Some(types::#name) ); } } } }