easy_from/
lib.rs

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 != &quote::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}