cgp_macro_lib/entrypoints/
derive_from_variant.rs

1use proc_macro2::TokenStream;
2use quote::quote;
3use syn::{ItemEnum, ItemImpl, parse2};
4
5use crate::derive_extractor::get_variant_type;
6use crate::symbol::symbol_from_string;
7
8pub fn derive_from_variant(body: TokenStream) -> syn::Result<TokenStream> {
9    let item_enum: ItemEnum = parse2(body)?;
10
11    derive_from_variant_from_enum(&item_enum)
12}
13
14pub fn derive_from_variant_from_enum(item_enum: &ItemEnum) -> syn::Result<TokenStream> {
15    let enum_ident = &item_enum.ident;
16
17    let (impl_generics, ty_generics, where_clause) = item_enum.generics.split_for_impl();
18
19    let mut item_impls: Vec<ItemImpl> = Vec::new();
20
21    for variant in item_enum.variants.iter() {
22        let variant_ident = &variant.ident;
23        let variant_tag = symbol_from_string(&variant_ident.to_string());
24        let variant_type = get_variant_type(variant)?;
25
26        let item_impl: ItemImpl = parse2(quote! {
27            impl #impl_generics FromVariant<#variant_tag> for #enum_ident #ty_generics
28            #where_clause
29            {
30                type Value = #variant_type;
31
32                fn from_variant(_tag: ::core::marker::PhantomData<#variant_tag>, value: Self::Value) -> Self {
33                    Self::#variant_ident(value)
34                }
35            }
36        })?;
37
38        item_impls.push(item_impl);
39    }
40
41    let out = quote! {
42        #(#item_impls)*
43    };
44
45    Ok(out)
46}