enum_conversion_derive/
lib.rs

1mod impls;
2mod parse_attributes;
3mod parse_enum;
4mod templates;
5
6extern crate proc_macro;
7
8use std::collections::HashMap;
9
10use proc_macro::TokenStream;
11use quote::ToTokens;
12use syn::DeriveInput;
13use tera::{Context, Tera};
14
15use crate::parse_attributes::{parse_custom_error_config, ErrorConfig};
16
17const ENUM_CONV_LIFETIME: &str = "'enum_conv";
18
19use crate::parse_enum::{
20    create_marker_enums, fetch_fields_from_enum, fetch_impl_generics,
21    fetch_name_with_generic_params, get_marker,
22};
23
24#[proc_macro_attribute]
25#[allow(non_snake_case)]
26pub fn EnumConversions(args: TokenStream, input: TokenStream) -> TokenStream {
27    let error_config = parse_custom_error_config(args.into());
28    let enum_ast = syn::parse(input).unwrap();
29
30    impl_conversions(error_config, enum_ast)
31}
32
33#[proc_macro_attribute]
34#[allow(non_snake_case)]
35pub fn DeriveTryFrom(_: TokenStream, input: TokenStream) -> TokenStream {
36    input
37}
38
39/// Implements ContainsVariant, GetVariant, SetVariant, and CreateVariantFrom traits
40fn impl_conversions(error_config: ErrorConfig, mut ast: DeriveInput) -> TokenStream {
41    let tera = templates::templater();
42    let name = &ast.ident.to_string();
43    let (fullname, lifetimes) = fetch_name_with_generic_params(&ast);
44    let impl_generics = fetch_impl_generics(&ast, ENUM_CONV_LIFETIME, &lifetimes);
45
46    let field_map = fetch_fields_from_enum(&mut ast);
47    let mut tokens: TokenStream = ast.to_token_stream().to_string().parse().unwrap();
48
49    tokens.extend::<TokenStream>(create_marker_enums(name, &field_map).parse().unwrap());
50    tokens.extend::<TokenStream>(
51        impls::impl_get_variant(name, &fullname, &impl_generics, &field_map, &tera)
52            .parse()
53            .unwrap(),
54    );
55    tokens.extend::<TokenStream>(
56        impls::impl_try_from(
57            name,
58            &fullname,
59            &impl_generics,
60            &error_config,
61            &field_map,
62            &tera,
63        )
64        .parse()
65        .unwrap(),
66    );
67    tokens.extend::<TokenStream>(
68        impls::impl_try_to(
69            name,
70            &fullname,
71            &impl_generics,
72            &error_config,
73            &field_map,
74            &tera,
75        )
76        .parse()
77        .unwrap(),
78    );
79    tokens.extend::<TokenStream>(
80        impls::impl_from(&fullname, &impl_generics, &field_map, &tera)
81            .parse()
82            .unwrap(),
83    );
84    tokens
85}