cgp_macro_lib/entrypoints/
derive_from_variant.rs1use 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}