enum-tools 0.5.5

Automatically derive functions and trait implementations for enums
Documentation
use crate::feature::iter::extend_common;
use crate::generator::features::Features1;
use crate::generator::names::Names;
use crate::generator::Derive;
use crate::parser::feature::FeatureParser;
use proc_macro2::TokenStream;
use quote::quote;
use syn::Visibility;

pub(crate) struct FeatureNames {
    pub(crate) enabled: bool,
    pub(crate) vis: Option<Visibility>,
    pub(crate) name: String,
    pub(crate) struct_name: Option<String>,
}

impl FeatureNames {
    pub(crate) fn parse(feature_parser: &mut FeatureParser) -> Self {
        if let Some(mut params) = feature_parser.get("names") {
            let (vis, name) = params.get_vis_name("names");

            let struct_name = params.get_str_opt("struct");

            params.finish(Self {
                enabled: true,
                vis,
                name,
                struct_name,
            })
        } else {
            Self {
                enabled: false,
                vis: Some(Visibility::Inherited),
                name: "__names".to_string(),
                struct_name: None,
            }
        }
    }

    pub(crate) fn check(&self, features: &mut Features1) {
        if !self.enabled {
            return;
        }

        features.table_name.enabled = true;
    }

    pub(crate) fn generate(&self, derive: &Derive, names: &Names) -> (TokenStream, TokenStream) {
        if !self.enabled {
            return (TokenStream::new(), TokenStream::new());
        }

        let Derive { ident_enum, .. } = derive;
        let Names {
            ident_names_fn,
            ident_names_struct,
            ident_table_name,
            ..
        } = names;
        let vis = self.vis.as_ref().unwrap_or(&derive.vis_enum);

        let doc_inner = format!(
            " An Iterator over the names of {ident_enum}, in value order.\n\
            \n\
            Use `Self::iter().zip(Self::names())` to iterate over pairs of\n\
            the item and it's name.",
        );
        let doc_outer = format!(" An Iterator over the names of {ident_enum}.");

        let inner = quote! {
            #[doc=#doc_inner]
            #[inline]
            #vis fn #ident_names_fn() -> #ident_names_struct {
                use ::core::iter::Iterator;
                #ident_names_struct{inner: Self::#ident_table_name.iter().copied()}
            }
        };

        let mut outer = quote! {
            #[doc=#doc_outer]
            #vis struct #ident_names_struct {
                inner: ::core::iter::Copied<::core::slice::Iter<'static, &'static str>>,
            }
        };

        extend_common(&mut outer, quote! {&'static str}, ident_names_struct, false);

        (inner, outer)
    }
}