Browse Source

update derive code to use synstructure/proc_macro2 and recent crate versions

preview
Stefan Bühler 2 years ago
parent
commit
1c7e385937
  1. 38
      Cargo.lock
  2. 36
      lib/dnsbox-base/src/ser/packet/std_impls.rs
  3. 36
      lib/dnsbox-base/src/ser/text/std_impls.rs
  4. 6
      lib/dnsbox-derive/Cargo.toml
  5. 111
      lib/dnsbox-derive/src/dns_packet_data.rs
  6. 104
      lib/dnsbox-derive/src/dns_text_data.rs
  7. 49
      lib/dnsbox-derive/src/lib.rs
  8. 75
      lib/dnsbox-derive/src/rrdata.rs

38
Cargo.lock

@ -143,8 +143,10 @@ dependencies = [
name = "dnsbox-derive"
version = "0.1.0"
dependencies = [
"quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.39 (registry+https://github.com/rust-lang/crates.io-index)",
"synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -344,11 +346,6 @@ dependencies = [
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "quote"
version = "0.3.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "quote"
version = "0.6.12"
@ -517,16 +514,6 @@ name = "stable_deref_trait"
version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "syn"
version = "0.11.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
"synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "syn"
version = "0.15.39"
@ -537,14 +524,6 @@ dependencies = [
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "synom"
version = "0.11.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "synstructure"
version = "0.10.2"
@ -752,11 +731,6 @@ dependencies = [
"tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "unicode-xid"
version = "0.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "unicode-xid"
version = "0.1.0"
@ -840,7 +814,6 @@ dependencies = [
"checksum parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337"
"checksum parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9"
"checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759"
"checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a"
"checksum quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "faf4799c5d274f3868a4aae320a0a182cbd2baee377b378f080e16a23e9d80db"
"checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca"
"checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef"
@ -863,9 +836,7 @@ dependencies = [
"checksum smallvec 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f90c5e5fe535e48807ab94fc611d323935f39d4660c52b26b96446a7b33aef10"
"checksum smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ab606a9c5e214920bb66c458cd7be8ef094f813f20fe77a54cc7dbfff220d4b7"
"checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8"
"checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad"
"checksum syn 0.15.39 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d960b829a55e56db167e861ddb43602c003c7be0bee1d345021703fac2fb7c"
"checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6"
"checksum synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "02353edf96d6e4dc81aea2d8490a7e9db177bf8acb0e951c24940bf866cb313f"
"checksum tokio 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)" = "ec2ffcf4bcfc641413fa0f1427bf8f91dfc78f56a6559cbf50e04837ae442a87"
"checksum tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5c501eceaf96f0e1793cf26beb63da3d11c738c4a943fdf3746d81d64684c39f"
@ -882,7 +853,6 @@ dependencies = [
"checksum tokio-trace-core 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9c8a256d6956f7cb5e2bdfe8b1e8022f1a09206c6c2b1ba00f3b746b260c613"
"checksum tokio-udp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "66268575b80f4a4a710ef83d087fdfeeabdce9b74c797535fbac18a2cb906e92"
"checksum tokio-uds 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "037ffc3ba0e12a0ab4aca92e5234e0dedeb48fddf6ccd260f1f150a36a9f2445"
"checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc"
"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
"checksum winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f10e386af2b13e47c89e7236a7a14a086791a2b88ebad6df9bf42040195cf770"

36
lib/dnsbox-base/src/ser/packet/std_impls.rs

@ -5,6 +5,26 @@ use std::io::{Cursor, Read};
use std::mem::size_of;
use std::net::{Ipv4Addr, Ipv6Addr};
impl DnsPacketData for () {
fn deserialize(_data: &mut Cursor<Bytes>) -> Result<Self> {
Ok(())
}
fn serialize(&self, _context: &mut DnsPacketWriteContext, _packet: &mut Vec<u8>) -> Result<()> {
Ok(())
}
}
impl<T: ?Sized> DnsPacketData for std::marker::PhantomData<T> {
fn deserialize(_data: &mut Cursor<Bytes>) -> Result<Self> {
Ok(std::marker::PhantomData)
}
fn serialize(&self, _context: &mut DnsPacketWriteContext, _packet: &mut Vec<u8>) -> Result<()> {
Ok(())
}
}
impl DnsPacketData for u8 {
fn deserialize(data: &mut Cursor<Bytes>) -> Result<Self> {
check_enough_data!(data, size_of::<Self>(), "u8");
@ -95,4 +115,20 @@ mod tests {
fn test_u16() {
assert!(deserialize::<u16>(b"\x80\x08").unwrap() == 0x8008);
}
#[derive(super::DnsPacketData, PartialEq, Eq, Debug)]
struct Unit;
#[test]
fn test_unit() {
assert_eq!(deserialize::<Unit>(b"").unwrap(), Unit);
}
#[derive(super::DnsPacketData, PartialEq, Eq, Debug)]
struct Tuple(u16);
#[test]
fn test_tuple() {
assert_eq!(deserialize::<Tuple>(b"\x04\xd2").unwrap(), Tuple(1234));
}
}

36
lib/dnsbox-base/src/ser/text/std_impls.rs

@ -2,6 +2,26 @@ use std::fmt;
use std::net::{Ipv4Addr, Ipv6Addr};
use crate::ser::text::{DnsTextData, DnsTextFormatter, DnsTextContext, next_field};
impl DnsTextData for () {
fn dns_parse(_context: &DnsTextContext, _data: &mut &str) -> crate::errors::Result<Self> {
Ok(())
}
fn dns_format(&self, _f: &mut DnsTextFormatter) -> fmt::Result {
Ok(())
}
}
impl<T: ?Sized> DnsTextData for std::marker::PhantomData<T> {
fn dns_parse(_context: &DnsTextContext, _data: &mut &str) -> crate::errors::Result<Self> {
Ok(std::marker::PhantomData)
}
fn dns_format(&self, _f: &mut DnsTextFormatter) -> fmt::Result {
Ok(())
}
}
/* only decimal representations are used for numbers */
impl DnsTextData for u8 {
fn dns_parse(_context: &DnsTextContext, data: &mut &str) -> crate::errors::Result<Self> {
@ -98,4 +118,20 @@ mod tests {
)
);
}
#[derive(DnsTextData, PartialEq, Eq, Debug)]
struct Unit;
#[test]
fn test_unit() {
assert_eq!(deserialize::<Unit>("").unwrap(), Unit);
}
#[derive(DnsTextData, PartialEq, Eq, Debug)]
struct Tuple(u16);
#[test]
fn test_tuple() {
assert_eq!(deserialize::<Tuple>("1234").unwrap(), Tuple(1234));
}
}

6
lib/dnsbox-derive/Cargo.toml

@ -8,5 +8,7 @@ edition = "2018"
proc-macro = true
[dependencies]
syn = "0.11"
quote = "0.3"
syn = "0.15.39"
quote = "0.6.12"
synstructure = "0.10.2"
proc-macro2 = "0.4.30"

111
lib/dnsbox-derive/src/dns_packet_data.rs

@ -1,59 +1,80 @@
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");
}
use proc_macro2::TokenStream;
if !ast.generics.where_clause.predicates.is_empty() {
panic!("Where clauses not supported for deriving DnsPacketData");
}
fn derive_impl(s: &synstructure::Structure, parse_fields: TokenStream, serialize_fields: TokenStream) -> TokenStream {
s.gen_impl(quote!{
#[allow(unused_imports)]
use dnsbox_base::_failure::ResultExt;
#[allow(unused_imports)]
use dnsbox_base::ser::packet::DnsPacketData;
if !ast.generics.lifetimes.is_empty() {
panic!("Lifetimes not supported for deriving DnsPacketData");
}
gen impl DnsPacketData for @Self {
fn deserialize(_data: &mut ::std::io::Cursor<::dnsbox_base::_bytes::Bytes>) -> ::dnsbox_base::errors::Result<Self> {
Ok(#parse_fields)
}
let name = &ast.ident;
#[allow(unused_imports)]
fn serialize(&self, _context: &mut ::dnsbox_base::ser::packet::DnsPacketWriteContext, _packet: &mut Vec<u8>) -> ::dnsbox_base::errors::Result<()> {
#serialize_fields
Ok(())
}
}
})
}
fn derive_unit(s: &synstructure::Structure) -> TokenStream {
let name = &s.ast().ident;
derive_impl(s, quote!{#name}, quote!{})
}
fn derive_named(s: &synstructure::Structure, fields: &syn::FieldsNamed) -> TokenStream {
let name = &s.ast().ident;
let mut parse_fields = quote!{};
let mut serialize_fields = quote!{};
for field in fields {
for field in &fields.named {
let field_name = field.ident.as_ref().unwrap();
let parse_ctx_msg = format!("failed parsing field {}::{}", name, field_name);
let serialize_ctx_msg = format!("failed serializing field {}::{}", name, field_name);
parse_fields = quote!{#parse_fields
#field_name: DnsPacketData::deserialize(_data).context(#parse_ctx_msg)?,
};
parse_fields.extend(quote!{
#field_name: DnsPacketData::deserialize(_data)
.with_context(|e| format!("failed parsing field {}::{}: {}", stringify!(#name), stringify!(#field_name), e))?,
});
serialize_fields = quote!{#serialize_fields
self.#field_name.serialize(_context, _packet).context(#serialize_ctx_msg)?;
};
serialize_fields.extend(quote!{
self.#field_name.serialize(_context, _packet)
.with_context(|e| format!("failed serializing field {}::{}: {}", stringify!(#name), stringify!(#field_name), e))?;
});
}
quote!{
impl ::dnsbox_base::ser::packet::DnsPacketData for #name {
#[allow(unused_imports)]
fn deserialize(_data: &mut ::std::io::Cursor<::dnsbox_base::_bytes::Bytes>) -> ::dnsbox_base::errors::Result<Self> {
use dnsbox_base::_failure::ResultExt;
use dnsbox_base::ser::packet::DnsPacketData;
Ok(#name{ #parse_fields })
}
derive_impl(s, quote!{#name{ #parse_fields }}, serialize_fields)
}
#[allow(unused_imports)]
fn serialize(&self, _context: &mut ::dnsbox_base::ser::packet::DnsPacketWriteContext, _packet: &mut Vec<u8>) -> ::dnsbox_base::errors::Result<()> {
use dnsbox_base::_failure::ResultExt;
use dnsbox_base::ser::packet::DnsPacketData;
#serialize_fields
Ok(())
}
}
fn derive_unnamed(s: &synstructure::Structure, fields: &syn::FieldsUnnamed) -> TokenStream {
let name = &s.ast().ident;
let mut parse_fields = quote!{};
let mut serialize_fields = quote!{};
for field in 0..fields.unnamed.len() {
parse_fields.extend(quote!{
DnsPacketData::deserialize(_data)
.with_context(|e| format!("failed parsing field {}::{}: {}", stringify!(#name), #field, e))?,
});
serialize_fields.extend(quote!{
self.#field.serialize(_context, _packet)
.with_context(|e| format!("failed serializing field {}::{}: {}", stringify!(#name), #field, e))?;
});
}
derive_impl(s, quote!{#name(#parse_fields)}, serialize_fields)
}
pub fn derive(s: synstructure::Structure) -> TokenStream {
let ast = s.ast();
match &ast.data {
syn::Data::Struct(syn::DataStruct{ fields: syn::Fields::Unit, .. }) => derive_unit(&s),
syn::Data::Struct(syn::DataStruct{ fields: syn::Fields::Named(fields), .. }) => derive_named(&s, fields),
syn::Data::Struct(syn::DataStruct{ fields: syn::Fields::Unnamed(fields), .. }) => derive_unnamed(&s, fields),
_ => panic!("Deriving DnsPacketData not supported for non struct types"),
}
}

104
lib/dnsbox-derive/src/dns_text_data.rs

@ -1,56 +1,78 @@
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");
}
use proc_macro2::TokenStream;
if !ast.generics.where_clause.predicates.is_empty() {
panic!("Where clauses not supported for deriving DnsTextData");
}
fn derive_impl(s: &synstructure::Structure, parse_fields: TokenStream, format_fields: TokenStream) -> TokenStream {
s.gen_impl(quote!{
#[allow(unused_imports)]
use dnsbox_base::_failure::ResultExt as _;
#[allow(unused_imports)]
use dnsbox_base::ser::text::DnsTextData as _;
if !ast.generics.lifetimes.is_empty() {
panic!("Lifetimes not supported for deriving DnsTextData");
}
gen impl ::dnsbox_base::ser::text::DnsTextData for @Self {
fn dns_parse(_context: &::dnsbox_base::ser::text::DnsTextContext, _data: &mut &str) -> ::dnsbox_base::errors::Result<Self> {
Ok(#parse_fields)
}
fn dns_format(&self, f: &mut ::dnsbox_base::ser::text::DnsTextFormatter) -> ::std::fmt::Result {
use std::fmt::{self, Write};
#format_fields
Ok(())
}
}
})
}
fn derive_unit(s: &synstructure::Structure) -> TokenStream {
let name = &s.ast().ident;
derive_impl(s, quote!{#name}, quote!{})
}
let name = &ast.ident;
fn derive_named(s: &synstructure::Structure, fields: &syn::FieldsNamed) -> TokenStream {
let name = &s.ast().ident;
let mut parse_fields = quote!{};
let mut format_fields = quote!{};
for field in fields {
for field in &fields.named {
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)))?,
};
parse_fields.extend(quote!{
#field_name: DnsTextData::dns_parse(_context, _data)
.with_context(|e| format!("failed parsing field {}::{}: {}", stringify!(#name), stringify!(#field_name), e))?,
});
format_fields = quote!{#format_fields
format_fields.extend(quote!{
DnsTextData::dns_format(&self.#field_name, f)?;
};
});
}
quote!{
#[allow(unused_imports)]
impl ::dnsbox_base::ser::text::DnsTextData for #name {
fn dns_parse(_context: &::dnsbox_base::ser::text::DnsTextContext, _data: &mut &str) -> ::dnsbox_base::errors::Result<Self> {
use dnsbox_base::_failure::ResultExt;
use dnsbox_base::ser::text::DnsTextData;
Ok(#name{ #parse_fields })
}
derive_impl(s, quote!{#name{ #parse_fields }}, format_fields)
}
fn dns_format(&self, f: &mut ::dnsbox_base::ser::text::DnsTextFormatter) -> ::std::fmt::Result {
use dnsbox_base::ser::text::DnsTextData;
use std::fmt::{self, Write};
#format_fields
Ok(())
}
}
fn derive_unnamed(s: &synstructure::Structure, fields: &syn::FieldsUnnamed) -> TokenStream {
let name = &s.ast().ident;
let mut parse_fields = quote!{};
let mut format_fields = quote!{};
for field in 0..fields.unnamed.len() {
parse_fields.extend(quote!{
DnsTextData::dns_parse(_context, _data)
.with_context(|e| format!("failed parsing field {}::{}: {}", stringify!(#name), #field, e))?,
});
format_fields.extend(quote!{
DnsTextData::dns_format(&self.#field, f)?;
});
}
derive_impl(s, quote!{#name(#parse_fields)}, format_fields)
}
pub fn derive(s: synstructure::Structure) -> TokenStream {
let ast = s.ast();
match &ast.data {
syn::Data::Struct(syn::DataStruct{ fields: syn::Fields::Unit, .. }) => derive_unit(&s),
syn::Data::Struct(syn::DataStruct{ fields: syn::Fields::Named(fields), .. }) => derive_named(&s, fields),
syn::Data::Struct(syn::DataStruct{ fields: syn::Fields::Unnamed(fields), .. }) => derive_unnamed(&s, fields),
_ => panic!("Deriving DnsTextData not supported for non struct types"),
}
}

49
lib/dnsbox-derive/src/lib.rs

@ -1,34 +1,40 @@
#![recursion_limit="128"]
extern crate proc_macro;
extern crate syn;
#[macro_use]
extern crate synstructure;
#[macro_use]
extern crate quote;
extern crate proc_macro2;
use proc_macro::TokenStream;
mod rrdata;
mod dns_packet_data;
mod dns_text_data;
mod rrdata;
fn attr_get_single_list_arg(attr: &syn::Attribute) -> quote::Tokens {
match attr.value {
syn::MetaItem::List(_, ref l) => {
if l.len() != 1 {
panic!("{:?} attribute requires exactly one argument", attr.name());
decl_derive!([DnsPacketData] => dns_packet_data::derive);
decl_derive!([DnsTextData] => dns_text_data::derive);
decl_derive!([RRData, attributes(RRTypeName, RRClass)] => rrdata::rrdata_derive);
fn attr_get_single_list_arg(attr_meta: &syn::Meta) -> proc_macro2::TokenStream {
match attr_meta {
syn::Meta::Word(_) => {
panic!("{:?} attribute requires an argument", attr_meta.name())
},
syn::Meta::List(l) => {
if l.nested.len() != 1 {
panic!("{:?} attribute requires exactly one argument", attr_meta.name());
}
let arg = &l[0];
let arg = *l.nested.first().unwrap().value();
quote!{#arg}
},
syn::MetaItem::NameValue(_, ref l) => {
quote!{#l}
},
_ => {
panic!("{:?} argument requires one argument like: [#{}(...)]", attr.name(), attr.name());
syn::Meta::NameValue(nv) => {
let lit = &nv.lit;
quote!{#lit}
},
}
}
/*
#[proc_macro_derive(DnsPacketData)]
pub fn derive_dns_packet_data(input: TokenStream) -> TokenStream {
let s = input.to_string();
@ -51,13 +57,4 @@ pub fn derive_dns_text_data(input: TokenStream) -> TokenStream {
gen.parse().unwrap()
}
#[proc_macro_derive(RRData, attributes(RRTypeName, RRClass))]
pub fn derive_rr_data(input: TokenStream) -> TokenStream {
let s = input.to_string();
let ast = syn::parse_derive_input(&s).unwrap();
let gen = rrdata::build(&ast);
gen.parse().unwrap()
}
*/

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

@ -1,12 +1,9 @@
use syn;
use quote;
use super::{attr_get_single_list_arg};
use crate::attr_get_single_list_arg;
#[derive(Clone,Debug)]
enum StructAttribute {
RRTypeName(quote::Tokens),
RRClass(quote::Tokens),
RRTypeName(proc_macro2::TokenStream),
RRClass(proc_macro2::TokenStream),
}
struct StructAttributeParser<'a>(pub &'a [syn::Attribute]);
@ -17,76 +14,72 @@ impl<'a> Iterator for StructAttributeParser<'a> {
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)));
},
"RRClass" => {
return Some(StructAttribute::RRClass(attr_get_single_list_arg(a)));
},
_ => (),
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)));
}
}
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;
pub fn rrdata_derive(s: synstructure::Structure) -> proc_macro2::TokenStream {
let name = &s.ast().ident;
let mut name_str = None;
let mut rr_class = None;
for attr in StructAttributeParser(&ast.attrs) {
for attr in StructAttributeParser(&s.ast().attrs) {
match attr {
StructAttribute::RRTypeName(name) => {
assert_eq!(name_str, None, "only one RRTypeName attribute allowed");
assert!(name_str.is_none(), "only one RRTypeName attribute allowed");
name_str = Some(name);
},
StructAttribute::RRClass(c) => {
assert_eq!(rr_class, None, "only one RRTypeName attribute allowed");
assert!(rr_class.is_none(), "only one RRTypeName attribute allowed");
rr_class = Some(c);
},
}
}
let name_str = name_str.unwrap_or_else(|| {
let name_str: &str = name.as_ref();
let name_str = format!("{}", name);
quote!{#name_str}
});
let rr_class = rr_class.unwrap_or_else(|| quote!{ANY});
let test_mod_name = syn::Ident::from(format!("test_rr_{}", name));
let test_mod_name = syn::Ident::new(&format!("test_rr_{}", name), proc_macro2::Span::call_site());
quote!{
impl ::dnsbox_base::ser::RRData for #name {
let impl_rrdata = s.unbound_impl(
quote!(::dnsbox_base::ser::RRData),
quote! {
fn clone_box(&self) -> Box<::dnsbox_base::ser::RRData> {
Box::new(self.clone() as #name) as _
Box::new(self.clone() as Self) as _
}
fn as_any(&self) -> &::std::any::Any {
self as _
}
}
},
);
impl ::dnsbox_base::ser::StaticRRData for #name {
let impl_static_rrdata = s.unbound_impl(
quote!(::dnsbox_base::ser::StaticRRData),
quote! {
const TYPE: ::dnsbox_base::common_types::Type = ::dnsbox_base::common_types::types::#name;
const NAME: &'static str = #name_str;
const CLASS: ::dnsbox_base::common_types::Class = ::dnsbox_base::common_types::classes::#rr_class;
}
},
);
quote! {
#impl_rrdata
#impl_static_rrdata
// #[cfg(test)]
#[allow(non_snake_case, unused_imports)]

Loading…
Cancel
Save