1use proc_macro::TokenStream;
11use quote::quote;
12use quote::ToTokens;
13use syn::parse_macro_input;
14use syn::Data;
15use syn::DataEnum;
16use syn::DeriveInput;
17use syn::Variant;
18
19#[proc_macro_attribute]
23pub fn add_field(_attr: TokenStream, input: TokenStream) -> TokenStream {
24 let mut item = parse_macro_input!(input as DeriveInput);
25 let item_name = item.ident.clone();
26
27 let unit_field = format!("Unit(OpUnitRcType<OpUnit<{}>>)", item_name);
28 let unit_field: TokenStream = unit_field.parse().expect("parse error");
29 let unit = parse_macro_input!(unit_field as Variant);
30
31 match item.data {
32 Data::Enum(DataEnum {
33 ref mut variants, ..
34 }) => {
35 variants.push(unit);
36 }
37 _ => panic!("only impl for enum"),
38 }
39
40 let tokens: proc_macro2::TokenStream = item.into_token_stream();
41 quote!(
42 #tokens
43 )
44 .into()
45}
46
47#[proc_macro_derive(OpUnitTrait)]
49pub fn impl_op_unit_trait(input: TokenStream) -> TokenStream {
50 let item = parse_macro_input!(input as DeriveInput);
51 let item_name = &item.ident;
52
53 quote!(
54 impl OpUnitTrait for #item_name {
55 fn get_op_unit(self: &OpUnitRcType<Self>) -> OpUnitRcType<OpUnit<Self>> {
56 match self.as_ref() {
57 #item_name::Unit(unit) => unit.clone(),
58 _ => OpUnitRcType::new(OpUnit::new(Some(self.clone()), None, Operation::Single)),
59 }
60 }
61 }
62 )
63 .into()
64}
65
66#[proc_macro_derive(BitAnd)]
68pub fn impl_bit_and(input: TokenStream) -> TokenStream {
69 let item = parse_macro_input!(input as DeriveInput);
70 let item_name = &item.ident;
71
72 quote!(
73 impl std::ops::BitAnd for #item_name {
74 type Output = Self;
75
76 fn bitand(self, rhs: Self) -> Self::Output {
77 let node = OpUnit::new(
78 Some(OpUnitRcType::new(self)),
79 Some(OpUnitRcType::new(rhs)),
80 Operation::And,
81 );
82 #item_name::Unit(OpUnitRcType::new(node))
83 }
84 }
85 )
86 .into()
87}
88
89#[proc_macro_derive(BitOr)]
91pub fn impl_bit_or(input: TokenStream) -> TokenStream {
92 let item = parse_macro_input!(input as DeriveInput);
93 let item_name = &item.ident;
94
95 quote!(
96 impl std::ops::BitOr for #item_name {
97 type Output = Self;
98
99 fn bitor(self, rhs: Self) -> Self::Output {
100 let node = OpUnit::new(
101 Some(OpUnitRcType::new(self)),
102 Some(OpUnitRcType::new(rhs)),
103 Operation::Or,
104 );
105 #item_name::Unit(OpUnitRcType::new(node))
106 }
107 }
108 )
109 .into()
110}