classic_bitfield/
lib.rs

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}