1use proc_macro::TokenStream;
2use quote::quote;
3use syn::{parse_macro_input, Data, DeriveInput, Fields};
4
5#[proc_macro_derive(EasyFrom, attributes(from))]
6pub fn derive_from(stream: TokenStream) -> TokenStream {
7 let input = parse_macro_input!(stream as DeriveInput);
8
9 let name = &input.ident;
10 let generics = &input.generics;
11
12 let mut out = TokenStream::new();
13 match input.data {
14 Data::Enum(e) => {
15 for v in e.variants.iter() {
16 let variant_name = &v.ident;
17 match &v.fields {
18 Fields::Unnamed(f) => {
19 let unnamed = &f.unnamed;
20 if unnamed.len() != 1 {
21 continue;
22 }
23
24 let field = &unnamed[0];
25 let attrs = &field.attrs;
26 if attrs.len() != 1 {
27 continue;
28 }
29
30 let attr = &attrs[0];
31 let path = &attr.path;
32 let segments = &path.segments;
33 if segments.len() != 1 {
34 continue;
35 }
36
37 let segment = &segments[0];
38 let ident = &segment.ident;
39
40 if ident != "e::format_ident!("from") {
41 continue;
42 }
43
44 let ty = &field.ty;
45
46 out.extend([TokenStream::from(quote! {
47 impl #generics core::convert::From<#ty> for #name #generics {
48 fn from(t: #ty) -> Self {
49 Self::#variant_name(t)
50 }
51 }
52 })]);
53 }
54 _ => (),
55 }
56 }
57 }
58 _ => unimplemented!(),
59 }
60
61 out
62}