1mod context;
2
3use proc_macro::TokenStream;
4use quote::quote;
5use syn::ItemEnum;
6
7use context::{BitfieldEnumCtx, ReprType};
8
9fn impl_bitfield_enum(ctx: BitfieldEnumCtx) -> TokenStream {
10 let type_name = &ctx.ident;
11 let repr_type = &*ctx.repr_type;
12 let visibility = &ctx.vis;
13 let struct_def = quote! {
14 struct #type_name(#repr_type);
15 };
16 let constant_values = ctx.constant_values();
17 let has_methods = ctx.has_methods();
18 let with_and_without = ctx.with_and_without();
19 let impl_iter_variants = ctx.impl_iter_variants();
20 let impl_from_and_deref = ctx.impl_from_and_deref();
21 let impl_bitand = ctx.impl_bitand();
22 let impl_bitor = ctx.impl_bitor();
23 let impl_partial_eq_ord = ctx.impl_partial_eq_ord();
24 let impl_debug = ctx.impl_debug();
25 let impl_not = ctx.impl_not();
26 let impl_serde = ctx.impl_serde();
27
28 quote! {
29 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
30 #visibility #struct_def
31
32 impl #type_name {
33 #(#constant_values)*
34
35 #(#has_methods)*
36
37 #with_and_without
38
39 #impl_iter_variants
40 }
41
42 #impl_from_and_deref
43
44 #impl_bitand
45
46 #impl_bitor
47
48 #impl_not
49
50 #impl_partial_eq_ord
51
52 #impl_debug
53
54 #impl_serde
55 }
56 .into()
57}
58
59#[proc_macro_attribute]
60pub fn bitfield_enum(attr: TokenStream, item: TokenStream) -> TokenStream {
61 let repr_type: ReprType = syn::parse(attr).expect("attribute should be empty or (as T)");
62 let enum_def: ItemEnum = syn::parse(item).expect("failed to parse input");
63 let ctx = BitfieldEnumCtx {
64 repr_type,
65 enum_def,
66 };
67 impl_bitfield_enum(ctx)
68}