tier-derive 0.1.17

Derive macros for tier Rust configuration metadata
Documentation
use syn::Attribute;

use crate::serde_attrs::model::{SerdeContainerAttrs, SerdeVariantAttrs};
use crate::syntax::{consume_unused_meta, parse_string_value, unraw};

use super::rename_meta::parse_rename_meta;

pub(crate) fn parse_serde_variant_attrs(
    attributes: &[Attribute],
    variant_ident: &syn::Ident,
    container_attrs: &SerdeContainerAttrs,
) -> syn::Result<SerdeVariantAttrs> {
    let base_name = unraw(variant_ident);
    let mut rename_serialize = None;
    let mut rename_deserialize = None;
    let mut aliases = Vec::new();
    let mut skip_metadata = false;

    for attribute in attributes {
        if !attribute.path().is_ident("serde") {
            continue;
        }

        attribute.parse_nested_meta(|meta| {
            if meta.path.is_ident("rename") {
                parse_rename_meta(meta, &mut rename_serialize, &mut rename_deserialize)?;
                return Ok(());
            }
            if meta.path.is_ident("alias") {
                aliases.push(parse_string_value(meta)?);
                return Ok(());
            }
            if meta.path.is_ident("skip")
                || meta.path.is_ident("skip_deserializing")
                || meta.path.is_ident("other")
            {
                skip_metadata = true;
                consume_unused_meta(meta)?;
                return Ok(());
            }
            consume_unused_meta(meta)?;
            Ok(())
        })?;
    }

    let canonical_name = rename_serialize
        .or_else(|| {
            container_attrs
                .rename_all_serialize
                .map(|rule| rule.apply_to_variant(&base_name))
        })
        .unwrap_or_else(|| base_name.clone());
    let deserialize_name = rename_deserialize
        .or_else(|| {
            container_attrs
                .rename_all_deserialize
                .map(|rule| rule.apply_to_variant(&base_name))
        })
        .unwrap_or_else(|| base_name.clone());

    if deserialize_name != canonical_name {
        aliases.push(deserialize_name);
    }

    aliases.retain(|alias| alias != &canonical_name);
    aliases.sort();
    aliases.dedup();

    Ok(SerdeVariantAttrs {
        canonical_name,
        aliases,
        skip_metadata,
    })
}