rust-dnsbox/lib/dnsbox-derive/src/rrdata.rs

105 lines
2.6 KiB
Rust
Raw Normal View History

2017-12-16 20:58:18 +00:00
use syn;
use quote;
2017-12-21 12:32:14 +00:00
use super::{attr_get_single_list_arg};
#[derive(Clone,Debug)]
enum StructAttribute {
RRTypeName(quote::Tokens),
2017-12-26 16:30:08 +00:00
RRClass(quote::Tokens),
2017-12-21 12:32:14 +00:00
}
struct StructAttributeParser<'a>(pub &'a [syn::Attribute]);
impl<'a> Iterator for StructAttributeParser<'a> {
type Item = StructAttribute;
fn next(&mut self) -> Option<Self::Item> {
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)));
},
2017-12-26 16:30:08 +00:00
"RRClass" => {
return Some(StructAttribute::RRClass(attr_get_single_list_arg(a)));
},
2017-12-21 12:32:14 +00:00
_ => (),
}
}
None
}
}
pub fn build(ast: &syn::DeriveInput) -> quote::Tokens {
2017-12-16 20:58:18 +00:00
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;
2017-12-26 16:30:08 +00:00
let mut name_str = None;
let mut rr_class = None;
2017-12-21 12:32:14 +00:00
for attr in StructAttributeParser(&ast.attrs) {
match attr {
StructAttribute::RRTypeName(name) => {
2017-12-26 16:30:08 +00:00
assert_eq!(name_str, None, "only one RRTypeName attribute allowed");
name_str = Some(name);
},
StructAttribute::RRClass(c) => {
assert_eq!(rr_class, None, "only one RRTypeName attribute allowed");
rr_class = Some(c);
2017-12-21 12:32:14 +00:00
},
}
}
2017-12-16 20:58:18 +00:00
2017-12-26 16:30:08 +00:00
let name_str = name_str.unwrap_or_else(|| {
let name_str: &str = name.as_ref();
quote!{#name_str}
});
let rr_class = rr_class.unwrap_or_else(|| quote!{ANY});
2017-12-16 20:58:18 +00:00
let test_mod_name = syn::Ident::from(format!("test_rr_{}", name));
quote!{
impl ::dnsbox_base::ser::RRData for #name {
2017-12-27 17:38:02 +00:00
fn clone_box(&self) -> Box<::dnsbox_base::ser::RRData> {
Box::new(self.clone() as #name) as _
}
2017-12-29 21:25:43 +00:00
fn as_any(&self) -> &::std::any::Any {
self as _
}
2017-12-21 12:32:14 +00:00
}
2017-12-16 20:58:18 +00:00
2017-12-21 12:32:14 +00:00
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;
2017-12-26 16:30:08 +00:00
const CLASS: ::dnsbox_base::common_types::Class = ::dnsbox_base::common_types::classes::#rr_class;
2017-12-16 20:58:18 +00:00
}
// #[cfg(test)]
#[allow(non_snake_case, unused_imports)]
mod #test_mod_name {
2017-12-21 12:32:14 +00:00
use dnsbox_base::records::registry;
use dnsbox_base::common_types::types;
use dnsbox_base::ser::StaticRRData;
2017-12-16 20:58:18 +00:00
#[test]
fn test_registry() {
registry::check_registration::<super::#name>();
2017-12-16 20:58:18 +00:00
}
}
}
}