2019-07-02 13:27:08 +00:00
|
|
|
use proc_macro2::TokenStream;
|
2017-12-21 12:32:14 +00:00
|
|
|
|
2019-07-02 13:27:08 +00:00
|
|
|
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 _;
|
2017-12-21 12:32:14 +00:00
|
|
|
|
2019-07-02 13:27:08 +00:00
|
|
|
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!{})
|
|
|
|
}
|
2017-12-21 12:32:14 +00:00
|
|
|
|
2019-07-02 13:27:08 +00:00
|
|
|
fn derive_named(s: &synstructure::Structure, fields: &syn::FieldsNamed) -> TokenStream {
|
|
|
|
let name = &s.ast().ident;
|
2017-12-21 12:32:14 +00:00
|
|
|
|
|
|
|
let mut parse_fields = quote!{};
|
|
|
|
let mut format_fields = quote!{};
|
2019-07-02 13:27:08 +00:00
|
|
|
for field in &fields.named {
|
2017-12-21 12:32:14 +00:00
|
|
|
let field_name = field.ident.as_ref().unwrap();
|
|
|
|
|
2019-07-02 13:27:08 +00:00
|
|
|
parse_fields.extend(quote!{
|
|
|
|
#field_name: DnsTextData::dns_parse(_context, _data)
|
|
|
|
.with_context(|e| format!("failed parsing field {}::{}: {}", stringify!(#name), stringify!(#field_name), e))?,
|
|
|
|
});
|
2017-12-21 12:32:14 +00:00
|
|
|
|
2019-07-02 13:27:08 +00:00
|
|
|
format_fields.extend(quote!{
|
2017-12-21 12:32:14 +00:00
|
|
|
DnsTextData::dns_format(&self.#field_name, f)?;
|
2019-07-02 13:27:08 +00:00
|
|
|
});
|
2017-12-21 12:32:14 +00:00
|
|
|
}
|
|
|
|
|
2019-07-02 13:27:08 +00:00
|
|
|
derive_impl(s, quote!{#name{ #parse_fields }}, format_fields)
|
|
|
|
}
|
2017-12-21 12:32:14 +00:00
|
|
|
|
2019-07-02 13:27:08 +00:00
|
|
|
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() {
|
2019-09-08 13:34:50 +00:00
|
|
|
let field = syn::Index::from(field);
|
2019-07-02 13:27:08 +00:00
|
|
|
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"),
|
2017-12-21 12:32:14 +00:00
|
|
|
}
|
|
|
|
}
|