use syn::{Attribute, Data, DeriveInput, Fields};
#[derive(Default)]
pub struct FieldAttrs {
pub into: bool,
}
#[derive(Default)]
pub struct VariantAttrs {
pub rename: Option<syn::Ident>,
}
pub fn parse_field_attrs(attrs: &[Attribute]) -> syn::Result<FieldAttrs> {
let mut result = FieldAttrs::default();
for attr in attrs {
if !attr.path().is_ident("flat") {
continue;
}
attr.parse_nested_meta(|meta| {
if meta.path.is_ident("into") {
result.into = true;
return Ok(());
}
Err(meta.error("expected `into`"))
})?;
}
Ok(result)
}
pub fn parse_variant_attrs(attrs: &[Attribute]) -> syn::Result<VariantAttrs> {
let mut result = VariantAttrs::default();
for attr in attrs {
if !attr.path().is_ident("flat") {
continue;
}
attr.parse_nested_meta(|meta| {
if meta.path.is_ident("rename") {
let value = meta.value()?;
let s: syn::LitStr = value.parse()?;
result.rename = Some(s.parse()?);
return Ok(());
}
Err(meta.error("expected `rename = \"...\"`"))
})?;
}
Ok(result)
}
pub fn validate_all_attrs(input: &DeriveInput) -> syn::Result<()> {
let validate_fields = |fields: &Fields| -> syn::Result<()> {
for f in fields {
parse_field_attrs(&f.attrs)?;
}
Ok(())
};
match &input.data {
Data::Struct(s) => validate_fields(&s.fields)?,
Data::Enum(e) => {
for v in &e.variants {
parse_variant_attrs(&v.attrs)?;
validate_fields(&v.fields)?;
}
}
Data::Union(_) => {}
}
Ok(())
}