numbat-codec-derive 0.0.9

Macro implementations of numbat-codec #[derive(NestedEncode, NestedDecode, TopEncode, TopDecode)]
Documentation
use quote::quote;

pub fn is_fieldless_enum(data_enum: &syn::DataEnum) -> bool {
	data_enum
		.variants
		.iter()
		.all(|variant| variant.fields.is_empty())
}

pub fn self_field_expr(index: usize, field: &syn::Field) -> proc_macro2::TokenStream {
	if let Some(ident) = &field.ident {
		quote! {
			self.#ident
		}
	} else {
		let index_lit = proc_macro2::Literal::usize_unsuffixed(index);
		quote! {
			self.#index_lit
		}
	}
}

pub fn local_variable_for_field(index: usize, field: &syn::Field) -> proc_macro2::TokenStream {
	if let Some(ident) = &field.ident {
		quote! {
			#ident
		}
	} else {
		let local_var_name = format!("unnamed_{}", index);
		let local_var_ident = syn::Ident::new(&local_var_name, proc_macro2::Span::call_site());
		quote! {
			#local_var_ident
		}
	}
}

pub fn fields_snippets<F>(fields: &syn::Fields, field_mapper: F) -> Vec<proc_macro2::TokenStream>
where
	F: Fn(usize, &syn::Field) -> proc_macro2::TokenStream,
{
	match fields {
		syn::Fields::Named(fields_named) => fields_named
			.named
			.iter()
			.enumerate()
			.map(|(index, field)| field_mapper(index, field))
			.collect(),
		syn::Fields::Unnamed(fields_unnamed) => fields_unnamed
			.unnamed
			.iter()
			.enumerate()
			.map(|(index, field)| field_mapper(index, field))
			.collect(),
		syn::Fields::Unit => Vec::new(),
	}
}

pub fn fields_decl_syntax<F>(fields: &syn::Fields, field_mapper: F) -> proc_macro2::TokenStream
where
	F: Fn(usize, &syn::Field) -> proc_macro2::TokenStream,
{
	match fields {
		syn::Fields::Named(fields_named) => {
			let local_variables: Vec<proc_macro2::TokenStream> = fields_named
				.named
				.iter()
				.enumerate()
				.map(|(index, field)| field_mapper(index, field))
				.collect();
			quote! {
				{ #(#local_variables),* }
			}
		},
		syn::Fields::Unnamed(fields_unnamed) => {
			let local_variables: Vec<proc_macro2::TokenStream> = fields_unnamed
				.unnamed
				.iter()
				.enumerate()
				.map(|(index, field)| field_mapper(index, field))
				.collect();
			quote! {
				( #(#local_variables),* )
			}
		},
		syn::Fields::Unit => quote! {},
	}
}