2019-07-02 13:27:08 +00:00
|
|
|
use crate::attr_get_single_list_arg;
|
2017-12-21 12:32:14 +00:00
|
|
|
|
2020-03-07 15:57:47 +00:00
|
|
|
#[derive(Clone, Debug)]
|
2017-12-21 12:32:14 +00:00
|
|
|
enum StructAttribute {
|
2019-07-02 13:27:08 +00:00
|
|
|
RRTypeName(proc_macro2::TokenStream),
|
|
|
|
RRClass(proc_macro2::TokenStream),
|
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..];
|
2019-07-02 13:27:08 +00:00
|
|
|
let meta = match a.interpret_meta() {
|
|
|
|
Some(m) => m,
|
|
|
|
_ => continue,
|
|
|
|
};
|
|
|
|
if meta.name() == "RRTypeName" {
|
|
|
|
return Some(StructAttribute::RRTypeName(attr_get_single_list_arg(&meta)));
|
|
|
|
}
|
|
|
|
if meta.name() == "RRClass" {
|
|
|
|
return Some(StructAttribute::RRClass(attr_get_single_list_arg(&meta)));
|
2017-12-21 12:32:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-07-02 13:27:08 +00:00
|
|
|
pub fn rrdata_derive(s: synstructure::Structure) -> proc_macro2::TokenStream {
|
|
|
|
let name = &s.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
|
|
|
|
2019-07-02 13:27:08 +00:00
|
|
|
for attr in StructAttributeParser(&s.ast().attrs) {
|
2017-12-21 12:32:14 +00:00
|
|
|
match attr {
|
|
|
|
StructAttribute::RRTypeName(name) => {
|
2019-07-02 13:27:08 +00:00
|
|
|
assert!(name_str.is_none(), "only one RRTypeName attribute allowed");
|
2017-12-26 16:30:08 +00:00
|
|
|
name_str = Some(name);
|
|
|
|
},
|
|
|
|
StructAttribute::RRClass(c) => {
|
2019-07-02 13:27:08 +00:00
|
|
|
assert!(rr_class.is_none(), "only one RRTypeName attribute allowed");
|
2017-12-26 16:30:08 +00:00
|
|
|
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(|| {
|
2019-07-02 13:27:08 +00:00
|
|
|
let name_str = format!("{}", name);
|
2020-03-07 15:57:47 +00:00
|
|
|
quote! {#name_str}
|
2017-12-26 16:30:08 +00:00
|
|
|
});
|
2020-03-07 15:57:47 +00:00
|
|
|
let rr_class = rr_class.unwrap_or_else(|| quote! {ANY});
|
2017-12-26 16:30:08 +00:00
|
|
|
|
2020-03-07 15:57:47 +00:00
|
|
|
let test_mod_name =
|
|
|
|
syn::Ident::new(&format!("test_rr_{}", name), proc_macro2::Span::call_site());
|
2017-12-16 20:58:18 +00:00
|
|
|
|
2019-07-02 13:27:08 +00:00
|
|
|
let impl_rrdata = s.unbound_impl(
|
|
|
|
quote!(::dnsbox_base::ser::RRData),
|
|
|
|
quote! {
|
2017-12-27 17:38:02 +00:00
|
|
|
fn clone_box(&self) -> Box<::dnsbox_base::ser::RRData> {
|
2019-07-02 13:27:08 +00:00
|
|
|
Box::new(self.clone() as Self) as _
|
2017-12-27 17:38:02 +00:00
|
|
|
}
|
2017-12-29 21:25:43 +00:00
|
|
|
|
|
|
|
fn as_any(&self) -> &::std::any::Any {
|
|
|
|
self as _
|
|
|
|
}
|
2020-03-07 18:05:00 +00:00
|
|
|
|
|
|
|
fn as_box_any(self: Box<Self>) -> Box<dyn ::std::any::Any> {
|
|
|
|
self as _
|
|
|
|
}
|
2019-07-02 13:27:08 +00:00
|
|
|
},
|
|
|
|
);
|
2017-12-16 20:58:18 +00:00
|
|
|
|
2019-07-02 13:27:08 +00:00
|
|
|
let impl_static_rrdata = s.unbound_impl(
|
|
|
|
quote!(::dnsbox_base::ser::StaticRRData),
|
|
|
|
quote! {
|
2017-12-21 12:32:14 +00:00
|
|
|
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;
|
2019-07-02 13:27:08 +00:00
|
|
|
},
|
|
|
|
);
|
|
|
|
|
|
|
|
quote! {
|
|
|
|
#impl_rrdata
|
|
|
|
#impl_static_rrdata
|
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() {
|
2019-07-01 08:57:57 +00:00
|
|
|
registry::check_registration::<super::#name>();
|
2017-12-16 20:58:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|