pub use attr_kw::delegator as kw_delegator;
use syn::{MacroDelimiter, MetaList, parse_quote};
use super::*;
mod attr_kw {
use super::*;
custom_keyword!(delegator);
}
#[derive(ToTokens)]
pub enum SaneVarFields {
Named(SaneVarFieldsNamed),
Unnamed(SaneVarFieldsUnnamed),
Unit,
}
impl SaneVarFields {
pub fn delegator_field_kw(&self) -> Option<&kw_delegator> {
match self {
SaneVarFields::Named(named) => named.delegator.as_ref().map(|(kw, _, _)| kw),
SaneVarFields::Unnamed(unnamed) => unnamed.delegator.as_ref().map(|(kw, _, _)| kw),
SaneVarFields::Unit => None,
}
}
}
pub struct SaneVarFieldsNamed {
pub fields: Brace<Punctuated<VarFieldNamed<SynMeta>, Token![,]>>,
pub delegator: Option<(kw_delegator, Ident, Type)>,
}
pub struct SaneVarFieldsUnnamed {
pub fields: Paren<Punctuated<VarFieldUnnamed<SynMeta>, Token![,]>>,
pub delegator: Option<(kw_delegator, usize, Type)>,
}
pub fn sanitize_variant_fields(input: VarFields<Meta<kw_delegator>>) -> Result<SaneVarFields> {
match input {
VarFields::Named(fields) => {
let (brace_token, fields) = fields.into_parts();
let mut delegator: Option<(kw_delegator, Ident, Type)> = None;
let mut new_fields = Punctuated::<VarFieldNamed<SynMeta>, Token![,]>::new();
for pair in fields.inner.into_pairs() {
let (input_field, comma) = pair.into_tuple();
let (new_field, delegator_option) = sanitize_field_named(input_field)?;
if let _Some(second) = delegator_option {
if let Some((first, _, _)) = delegator {
err_expected_only_one!(first, second);
} else {
delegator = Some((second, new_field.ident.clone(), new_field.ty.clone()));
}
}
new_fields.push_value(new_field);
if let Some(comma) = comma {
new_fields.push_punct(comma);
}
}
Ok(SaneVarFields::Named(SaneVarFieldsNamed {
fields: Brace::from((brace_token, new_fields)),
delegator,
}))
}
VarFields::Unnamed(fields) => {
let (paren_token, fields) = fields.into_parts();
let mut delegator: Option<(kw_delegator, usize, Type)> = None;
let mut new_fields = Punctuated::<VarFieldUnnamed<SynMeta>, Token![,]>::new();
for (idx, pair) in fields.inner.into_pairs().enumerate() {
let (input_field, comma) = pair.into_tuple();
let (new_field, delegator_option) = sanitize_field_unnamed(input_field)?;
if let _Some(second) = delegator_option {
if let Some((first, _, _)) = delegator {
err_expected_only_one!(first, second);
} else {
delegator = Some((second, idx, new_field.ty.clone()));
}
}
new_fields.push_value(new_field);
if let Some(comma) = comma {
new_fields.push_punct(comma);
}
}
Ok(SaneVarFields::Unnamed(SaneVarFieldsUnnamed {
fields: Paren::from((paren_token, new_fields)),
delegator,
}))
}
VarFields::Unit => Ok(SaneVarFields::Unit),
}
}
fn sanitize_field_named(
field: VarFieldNamed<Meta<kw_delegator>>,
) -> Result<(VarFieldNamed<SynMeta>, Optional<kw_delegator>)> {
let VarFieldNamed {
attrs,
ident,
colon_token,
ty,
} = field;
let (mut syn_attrs, cfg_attrs, custom_metas) = split_input_attrs(attrs.into_inner());
syn_attrs.extend(cfg_attrs.into_inner().into_iter().map(|cfg_attr| {
let kw = cfg_attr.inner.kw;
let (bracket, inner) = cfg_attr.inner.into_parts();
let (paren, tokens) = inner.tokens.into_parts();
Attribute {
pound_token: cfg_attr.pound_token,
inner: Bracket::from((
bracket,
SynMeta::List(MetaList {
path: parse_quote! { #kw },
delimiter: MacroDelimiter::Paren(paren),
tokens,
}),
)),
}
}));
let mut delegator: Optional<kw_delegator> = _None;
for attr in custom_metas {
let kw = attr.inner.into_inner();
assign_unique_or_panic!(delegator, kw);
}
Ok((
VarFieldNamed {
attrs: syn_attrs,
ident,
colon_token,
ty,
},
delegator,
))
}
fn sanitize_field_unnamed(
field: VarFieldUnnamed<Meta<kw_delegator>>,
) -> Result<(VarFieldUnnamed<SynMeta>, Optional<kw_delegator>)> {
let VarFieldUnnamed { attrs, ty } = field;
let (mut syn_attrs, cfg_attrs, custom_metas) = split_input_attrs(attrs.into_inner());
syn_attrs.extend(cfg_attrs.into_inner().into_iter().map(|cfg_attr| {
let kw = cfg_attr.inner.kw;
let (bracket, inner) = cfg_attr.inner.into_parts();
let (paren, tokens) = inner.tokens.into_parts();
Attribute {
pound_token: cfg_attr.pound_token,
inner: Bracket::from((
bracket,
SynMeta::List(MetaList {
path: parse_quote! { #kw },
delimiter: MacroDelimiter::Paren(paren),
tokens,
}),
)),
}
}));
let mut delegator: Optional<kw_delegator> = _None;
for attr in custom_metas {
let kw = attr.inner.into_inner();
assign_unique_or_panic!(delegator, kw);
}
Ok((
VarFieldUnnamed {
attrs: syn_attrs,
ty,
},
delegator,
))
}
impl ToTokens for SaneVarFieldsNamed {
fn to_tokens(&self, tokens: &mut TokenStream) {
self.fields.to_tokens(tokens);
}
}
impl ToTokens for SaneVarFieldsUnnamed {
fn to_tokens(&self, tokens: &mut TokenStream) {
self.fields.to_tokens(tokens);
}
}