update derive code to use synstructure/proc_macro2 and recent crate versions
This commit is contained in:
parent
174314cbcb
commit
1c7e385937
38
Cargo.lock
generated
38
Cargo.lock
generated
@ -143,8 +143,10 @@ dependencies = [
|
|||||||
name = "dnsbox-derive"
|
name = "dnsbox-derive"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
"proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"syn 0.11.11 (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]]
|
[[package]]
|
||||||
@ -344,11 +346,6 @@ dependencies = [
|
|||||||
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"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]]
|
[[package]]
|
||||||
name = "quote"
|
name = "quote"
|
||||||
version = "0.6.12"
|
version = "0.6.12"
|
||||||
@ -517,16 +514,6 @@ name = "stable_deref_trait"
|
|||||||
version = "1.1.1"
|
version = "1.1.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
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]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "0.15.39"
|
version = "0.15.39"
|
||||||
@ -537,14 +524,6 @@ dependencies = [
|
|||||||
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"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]]
|
[[package]]
|
||||||
name = "synstructure"
|
name = "synstructure"
|
||||||
version = "0.10.2"
|
version = "0.10.2"
|
||||||
@ -752,11 +731,6 @@ dependencies = [
|
|||||||
"tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
"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]]
|
[[package]]
|
||||||
name = "unicode-xid"
|
name = "unicode-xid"
|
||||||
version = "0.1.0"
|
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 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 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 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 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 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"
|
"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.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 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 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 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 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 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"
|
"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-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-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 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 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.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"
|
"checksum winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f10e386af2b13e47c89e7236a7a14a086791a2b88ebad6df9bf42040195cf770"
|
||||||
|
@ -5,6 +5,26 @@ use std::io::{Cursor, Read};
|
|||||||
use std::mem::size_of;
|
use std::mem::size_of;
|
||||||
use std::net::{Ipv4Addr, Ipv6Addr};
|
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 {
|
impl DnsPacketData for u8 {
|
||||||
fn deserialize(data: &mut Cursor<Bytes>) -> Result<Self> {
|
fn deserialize(data: &mut Cursor<Bytes>) -> Result<Self> {
|
||||||
check_enough_data!(data, size_of::<Self>(), "u8");
|
check_enough_data!(data, size_of::<Self>(), "u8");
|
||||||
@ -95,4 +115,20 @@ mod tests {
|
|||||||
fn test_u16() {
|
fn test_u16() {
|
||||||
assert!(deserialize::<u16>(b"\x80\x08").unwrap() == 0x8008);
|
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));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,26 @@ use std::fmt;
|
|||||||
use std::net::{Ipv4Addr, Ipv6Addr};
|
use std::net::{Ipv4Addr, Ipv6Addr};
|
||||||
use crate::ser::text::{DnsTextData, DnsTextFormatter, DnsTextContext, next_field};
|
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 */
|
/* only decimal representations are used for numbers */
|
||||||
impl DnsTextData for u8 {
|
impl DnsTextData for u8 {
|
||||||
fn dns_parse(_context: &DnsTextContext, data: &mut &str) -> crate::errors::Result<Self> {
|
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));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,5 +8,7 @@ edition = "2018"
|
|||||||
proc-macro = true
|
proc-macro = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
syn = "0.11"
|
syn = "0.15.39"
|
||||||
quote = "0.3"
|
quote = "0.6.12"
|
||||||
|
synstructure = "0.10.2"
|
||||||
|
proc-macro2 = "0.4.30"
|
||||||
|
@ -1,59 +1,80 @@
|
|||||||
use syn;
|
use proc_macro2::TokenStream;
|
||||||
use quote;
|
|
||||||
|
|
||||||
pub fn build(ast: &syn::DeriveInput) -> quote::Tokens {
|
fn derive_impl(s: &synstructure::Structure, parse_fields: TokenStream, serialize_fields: TokenStream) -> TokenStream {
|
||||||
let fields = match ast.body {
|
s.gen_impl(quote!{
|
||||||
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");
|
|
||||||
}
|
|
||||||
|
|
||||||
if !ast.generics.where_clause.predicates.is_empty() {
|
|
||||||
panic!("Where clauses not supported for deriving DnsPacketData");
|
|
||||||
}
|
|
||||||
|
|
||||||
if !ast.generics.lifetimes.is_empty() {
|
|
||||||
panic!("Lifetimes not supported for deriving DnsPacketData");
|
|
||||||
}
|
|
||||||
|
|
||||||
let name = &ast.ident;
|
|
||||||
|
|
||||||
let mut parse_fields = quote!{};
|
|
||||||
let mut serialize_fields = quote!{};
|
|
||||||
for field in fields {
|
|
||||||
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)?,
|
|
||||||
};
|
|
||||||
|
|
||||||
serialize_fields = quote!{#serialize_fields
|
|
||||||
self.#field_name.serialize(_context, _packet).context(#serialize_ctx_msg)?;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
quote!{
|
|
||||||
impl ::dnsbox_base::ser::packet::DnsPacketData for #name {
|
|
||||||
#[allow(unused_imports)]
|
#[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::_failure::ResultExt;
|
||||||
|
#[allow(unused_imports)]
|
||||||
use dnsbox_base::ser::packet::DnsPacketData;
|
use dnsbox_base::ser::packet::DnsPacketData;
|
||||||
Ok(#name{ #parse_fields })
|
|
||||||
|
gen impl DnsPacketData for @Self {
|
||||||
|
fn deserialize(_data: &mut ::std::io::Cursor<::dnsbox_base::_bytes::Bytes>) -> ::dnsbox_base::errors::Result<Self> {
|
||||||
|
Ok(#parse_fields)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
fn serialize(&self, _context: &mut ::dnsbox_base::ser::packet::DnsPacketWriteContext, _packet: &mut Vec<u8>) -> ::dnsbox_base::errors::Result<()> {
|
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
|
#serialize_fields
|
||||||
Ok(())
|
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.named {
|
||||||
|
let field_name = field.ident.as_ref().unwrap();
|
||||||
|
|
||||||
|
parse_fields.extend(quote!{
|
||||||
|
#field_name: DnsPacketData::deserialize(_data)
|
||||||
|
.with_context(|e| format!("failed parsing field {}::{}: {}", stringify!(#name), stringify!(#field_name), e))?,
|
||||||
|
});
|
||||||
|
|
||||||
|
serialize_fields.extend(quote!{
|
||||||
|
self.#field_name.serialize(_context, _packet)
|
||||||
|
.with_context(|e| format!("failed serializing field {}::{}: {}", stringify!(#name), stringify!(#field_name), e))?;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
derive_impl(s, quote!{#name{ #parse_fields }}, serialize_fields)
|
||||||
|
}
|
||||||
|
|
||||||
|
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"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,56 +1,78 @@
|
|||||||
use syn;
|
use proc_macro2::TokenStream;
|
||||||
use quote;
|
|
||||||
|
|
||||||
pub fn build(ast: &syn::DeriveInput) -> quote::Tokens {
|
fn derive_impl(s: &synstructure::Structure, parse_fields: TokenStream, format_fields: TokenStream) -> TokenStream {
|
||||||
let fields = match ast.body {
|
s.gen_impl(quote!{
|
||||||
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)]
|
#[allow(unused_imports)]
|
||||||
impl ::dnsbox_base::ser::text::DnsTextData for #name {
|
use dnsbox_base::_failure::ResultExt as _;
|
||||||
|
#[allow(unused_imports)]
|
||||||
|
use dnsbox_base::ser::text::DnsTextData as _;
|
||||||
|
|
||||||
|
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> {
|
fn dns_parse(_context: &::dnsbox_base::ser::text::DnsTextContext, _data: &mut &str) -> ::dnsbox_base::errors::Result<Self> {
|
||||||
use dnsbox_base::_failure::ResultExt;
|
Ok(#parse_fields)
|
||||||
use dnsbox_base::ser::text::DnsTextData;
|
|
||||||
Ok(#name{ #parse_fields })
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dns_format(&self, f: &mut ::dnsbox_base::ser::text::DnsTextFormatter) -> ::std::fmt::Result {
|
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};
|
use std::fmt::{self, Write};
|
||||||
#format_fields
|
#format_fields
|
||||||
Ok(())
|
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 format_fields = quote!{};
|
||||||
|
for field in &fields.named {
|
||||||
|
let field_name = field.ident.as_ref().unwrap();
|
||||||
|
|
||||||
|
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.extend(quote!{
|
||||||
|
DnsTextData::dns_format(&self.#field_name, f)?;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
derive_impl(s, quote!{#name{ #parse_fields }}, format_fields)
|
||||||
|
}
|
||||||
|
|
||||||
|
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"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,34 +1,40 @@
|
|||||||
#![recursion_limit="128"]
|
#![recursion_limit="128"]
|
||||||
|
|
||||||
extern crate proc_macro;
|
#[macro_use]
|
||||||
extern crate syn;
|
extern crate synstructure;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate quote;
|
extern crate quote;
|
||||||
|
extern crate proc_macro2;
|
||||||
|
|
||||||
use proc_macro::TokenStream;
|
mod rrdata;
|
||||||
|
|
||||||
mod dns_packet_data;
|
mod dns_packet_data;
|
||||||
mod dns_text_data;
|
mod dns_text_data;
|
||||||
mod rrdata;
|
|
||||||
|
|
||||||
fn attr_get_single_list_arg(attr: &syn::Attribute) -> quote::Tokens {
|
decl_derive!([DnsPacketData] => dns_packet_data::derive);
|
||||||
match attr.value {
|
decl_derive!([DnsTextData] => dns_text_data::derive);
|
||||||
syn::MetaItem::List(_, ref l) => {
|
decl_derive!([RRData, attributes(RRTypeName, RRClass)] => rrdata::rrdata_derive);
|
||||||
if l.len() != 1 {
|
|
||||||
panic!("{:?} attribute requires exactly one argument", attr.name());
|
|
||||||
|
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}
|
quote!{#arg}
|
||||||
},
|
},
|
||||||
syn::MetaItem::NameValue(_, ref l) => {
|
syn::Meta::NameValue(nv) => {
|
||||||
quote!{#l}
|
let lit = &nv.lit;
|
||||||
},
|
quote!{#lit}
|
||||||
_ => {
|
|
||||||
panic!("{:?} argument requires one argument like: [#{}(...)]", attr.name(), attr.name());
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
#[proc_macro_derive(DnsPacketData)]
|
#[proc_macro_derive(DnsPacketData)]
|
||||||
pub fn derive_dns_packet_data(input: TokenStream) -> TokenStream {
|
pub fn derive_dns_packet_data(input: TokenStream) -> TokenStream {
|
||||||
let s = input.to_string();
|
let s = input.to_string();
|
||||||
@ -51,13 +57,4 @@ pub fn derive_dns_text_data(input: TokenStream) -> TokenStream {
|
|||||||
gen.parse().unwrap()
|
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()
|
|
||||||
}
|
|
@ -1,12 +1,9 @@
|
|||||||
use syn;
|
use crate::attr_get_single_list_arg;
|
||||||
use quote;
|
|
||||||
|
|
||||||
use super::{attr_get_single_list_arg};
|
|
||||||
|
|
||||||
#[derive(Clone,Debug)]
|
#[derive(Clone,Debug)]
|
||||||
enum StructAttribute {
|
enum StructAttribute {
|
||||||
RRTypeName(quote::Tokens),
|
RRTypeName(proc_macro2::TokenStream),
|
||||||
RRClass(quote::Tokens),
|
RRClass(proc_macro2::TokenStream),
|
||||||
}
|
}
|
||||||
|
|
||||||
struct StructAttributeParser<'a>(pub &'a [syn::Attribute]);
|
struct StructAttributeParser<'a>(pub &'a [syn::Attribute]);
|
||||||
@ -17,76 +14,72 @@ impl<'a> Iterator for StructAttributeParser<'a> {
|
|||||||
while !self.0.is_empty() {
|
while !self.0.is_empty() {
|
||||||
let a = &self.0[0];
|
let a = &self.0[0];
|
||||||
self.0 = &self.0[1..];
|
self.0 = &self.0[1..];
|
||||||
if a.is_sugared_doc { continue; }
|
let meta = match a.interpret_meta() {
|
||||||
match a.value.name() {
|
Some(m) => m,
|
||||||
"RRTypeName" => {
|
_ => continue,
|
||||||
return Some(StructAttribute::RRTypeName(attr_get_single_list_arg(a)));
|
};
|
||||||
},
|
if meta.name() == "RRTypeName" {
|
||||||
"RRClass" => {
|
return Some(StructAttribute::RRTypeName(attr_get_single_list_arg(&meta)));
|
||||||
return Some(StructAttribute::RRClass(attr_get_single_list_arg(a)));
|
}
|
||||||
},
|
if meta.name() == "RRClass" {
|
||||||
_ => (),
|
return Some(StructAttribute::RRClass(attr_get_single_list_arg(&meta)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn build(ast: &syn::DeriveInput) -> quote::Tokens {
|
pub fn rrdata_derive(s: synstructure::Structure) -> proc_macro2::TokenStream {
|
||||||
if !ast.generics.ty_params.is_empty() {
|
let name = &s.ast().ident;
|
||||||
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 = None;
|
let mut name_str = None;
|
||||||
let mut rr_class = None;
|
let mut rr_class = None;
|
||||||
|
|
||||||
for attr in StructAttributeParser(&ast.attrs) {
|
for attr in StructAttributeParser(&s.ast().attrs) {
|
||||||
match attr {
|
match attr {
|
||||||
StructAttribute::RRTypeName(name) => {
|
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);
|
name_str = Some(name);
|
||||||
},
|
},
|
||||||
StructAttribute::RRClass(c) => {
|
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);
|
rr_class = Some(c);
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let name_str = name_str.unwrap_or_else(|| {
|
let name_str = name_str.unwrap_or_else(|| {
|
||||||
let name_str: &str = name.as_ref();
|
let name_str = format!("{}", name);
|
||||||
quote!{#name_str}
|
quote!{#name_str}
|
||||||
});
|
});
|
||||||
let rr_class = rr_class.unwrap_or_else(|| quote!{ANY});
|
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!{
|
let impl_rrdata = s.unbound_impl(
|
||||||
impl ::dnsbox_base::ser::RRData for #name {
|
quote!(::dnsbox_base::ser::RRData),
|
||||||
|
quote! {
|
||||||
fn clone_box(&self) -> Box<::dnsbox_base::ser::RRData> {
|
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 {
|
fn as_any(&self) -> &::std::any::Any {
|
||||||
self as _
|
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 TYPE: ::dnsbox_base::common_types::Type = ::dnsbox_base::common_types::types::#name;
|
||||||
const NAME: &'static str = #name_str;
|
const NAME: &'static str = #name_str;
|
||||||
const CLASS: ::dnsbox_base::common_types::Class = ::dnsbox_base::common_types::classes::#rr_class;
|
const CLASS: ::dnsbox_base::common_types::Class = ::dnsbox_base::common_types::classes::#rr_class;
|
||||||
}
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
quote! {
|
||||||
|
#impl_rrdata
|
||||||
|
#impl_static_rrdata
|
||||||
|
|
||||||
// #[cfg(test)]
|
// #[cfg(test)]
|
||||||
#[allow(non_snake_case, unused_imports)]
|
#[allow(non_snake_case, unused_imports)]
|
||||||
|
Loading…
Reference in New Issue
Block a user