derive_cmp_ops/
lib.rs

1use proc_macro2::{self, TokenStream};
2use quote::{quote, quote_spanned};
3use syn::{parse_macro_input, spanned::Spanned, Data, DeriveInput, Fields};
4///component wise addition derive.
5#[proc_macro_derive(CmpAdd)]
6pub fn cmp_add(item: proc_macro::TokenStream) -> proc_macro::TokenStream{
7    let input = parse_macro_input!(item as DeriveInput);
8    let name = input.ident;
9    let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
10
11    let sum = cmp_action(input.data, quote! {+});
12    proc_macro::TokenStream::from(quote! {
13        impl #impl_generics std::ops::Add for #name #ty_generics #where_clause{
14            fn add(self, rhs: Self) -> Self::Output{
15                #sum
16            }
17            type Output = Self;
18        }
19    })
20}
21///component wise addition assign derive.
22#[proc_macro_derive(CmpAddAssign)]
23pub fn cmp_add_assign(item: proc_macro::TokenStream) -> proc_macro::TokenStream{
24    let input = parse_macro_input!(item as DeriveInput);
25    let name = input.ident;
26    let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
27
28    let sum = cmp_action(input.data, quote! {+});
29    proc_macro::TokenStream::from(quote! {
30        impl #impl_generics std::ops::AddAssign for #name #ty_generics #where_clause{
31            fn add_assign(&mut self, rhs: Self){
32                *self = #sum
33            }
34        }
35    })
36}
37///component wise subtraction derive.
38#[proc_macro_derive(CmpSub)]
39pub fn cmp_sub(item: proc_macro::TokenStream) -> proc_macro::TokenStream{
40    let input = parse_macro_input!(item as DeriveInput);
41    let name = input.ident;
42    let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
43
44    let sum = cmp_action(input.data, quote! {-});
45    proc_macro::TokenStream::from(quote! {
46        impl #impl_generics std::ops::Sub for #name #ty_generics #where_clause{
47            fn sub(self, rhs: Self) -> Self::Output{
48                #sum
49            }
50            type Output = Self;
51        }
52    })
53}
54///component wise subtraction assign derive.
55#[proc_macro_derive(CmpSubAssign)]
56pub fn cmp_sub_assign(item: proc_macro::TokenStream) -> proc_macro::TokenStream{
57    let input = parse_macro_input!(item as DeriveInput);
58    let name = input.ident;
59    let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
60
61    let sum = cmp_action(input.data, quote! {-});
62    proc_macro::TokenStream::from(quote! {
63        impl #impl_generics std::ops::SubAssign for #name #ty_generics #where_clause{
64            fn sub_assign(&mut self, rhs: Self){
65                *self = #sum
66            }
67        }
68    })
69}
70///component wise multiplication derive.
71#[proc_macro_derive(CmpMul)]
72pub fn cmp_mul(item: proc_macro::TokenStream) -> proc_macro::TokenStream{
73    let input = parse_macro_input!(item as DeriveInput);
74    let name = input.ident;
75    let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
76
77    let sum = cmp_action(input.data, quote! {*});
78    proc_macro::TokenStream::from(quote! {
79        impl #impl_generics std::ops::Mul for #name #ty_generics #where_clause{
80            fn mul(self, rhs: Self) -> Self::Output{
81                #sum
82            }
83            type Output = Self;
84        }
85    })
86}
87///component wise multiplication assign derive.
88#[proc_macro_derive(CmpMulAssign)]
89pub fn cmp_mul_assign(item: proc_macro::TokenStream) -> proc_macro::TokenStream{
90    let input = parse_macro_input!(item as DeriveInput);
91    let name = input.ident;
92    let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
93
94    let sum = cmp_action(input.data, quote! {*});
95    proc_macro::TokenStream::from(quote! {
96        impl #impl_generics std::ops::MulAssign for #name #ty_generics #where_clause{
97            fn mul_assign(&mut self, rhs: Self){
98                *self = #sum
99            }
100        }
101    })
102}
103///component wise division derive.
104#[proc_macro_derive(CmpDiv)]
105pub fn cmp_div(item: proc_macro::TokenStream) -> proc_macro::TokenStream{
106    let input = parse_macro_input!(item as DeriveInput);
107    let name = input.ident;
108    let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
109    
110    let sum = cmp_action(input.data, quote! {/});
111    proc_macro::TokenStream::from(quote! {
112        impl #impl_generics std::ops::Div for #name #ty_generics #where_clause{
113            fn div(self, rhs: Self) -> Self::Output{
114                #sum
115            }
116            type Output = Self;
117        }
118    })
119}
120///component wise division assign derive.
121#[proc_macro_derive(CmpDivAssign)]
122pub fn cmp_div_assign(item: proc_macro::TokenStream) -> proc_macro::TokenStream{
123    let input = parse_macro_input!(item as DeriveInput);
124    let name = input.ident;
125    let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
126    
127    let sum = cmp_action(input.data, quote! {/});
128    proc_macro::TokenStream::from(quote! {
129        impl #impl_generics std::ops::DivAssign for #name #ty_generics #where_clause{
130            fn div_assign(&mut self, rhs: Self){
131                *self = #sum
132            }
133        }
134    })
135}
136///component wise remainder derive.
137#[proc_macro_derive(CmpRem)]
138pub fn cmp_rem(item: proc_macro::TokenStream) -> proc_macro::TokenStream{
139    let input = parse_macro_input!(item as DeriveInput);
140    let name = input.ident;
141    let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
142    
143    let sum = cmp_action(input.data, quote! {%});
144    proc_macro::TokenStream::from(quote! {
145        impl #impl_generics std::ops::Rem for #name #ty_generics #where_clause{
146            fn rem(self, rhs: Self) -> Self::Output{
147                #sum
148            }
149            type Output = Self;
150        }
151    })
152}
153///component wise remainder assign derive.
154#[proc_macro_derive(CmpRemAssign)]
155pub fn cmp_rem_assign(item: proc_macro::TokenStream) -> proc_macro::TokenStream{
156    let input = parse_macro_input!(item as DeriveInput);
157    let name = input.ident;
158    let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
159    
160    let sum = cmp_action(input.data, quote! {%});
161    proc_macro::TokenStream::from(quote! {
162        impl #impl_generics std::ops::RemAssign for #name #ty_generics #where_clause{
163            fn rem_assign(&mut self, rhs: Self){
164                *self = #sum
165            }
166        }
167    })
168}
169///component wise negative derive.
170#[proc_macro_derive(CmpNeg)]
171pub fn cmp_neg(item: proc_macro::TokenStream) -> proc_macro::TokenStream{
172    let input = parse_macro_input!(item as DeriveInput);
173    let name = input.ident;
174    let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
175    
176    let Data::Struct(ref data) = input.data else { unimplemented!() };
177    let Fields::Named(ref fields) = data.fields else { unimplemented!() };
178    let recursive = fields.named.iter().map(|f|{
179        let name = &f.ident;
180        quote_spanned! { f.span() => #name: -self.#name, }
181    });
182    let sum = quote! {
183        Self { #(#recursive)* }
184    };
185    proc_macro::TokenStream::from(quote! {
186        impl #impl_generics std::ops::Neg for #name #ty_generics #where_clause{
187            type Output = Self;
188            fn neg(self) -> Self::Output{
189                #sum
190            }
191        }
192    })
193}
194fn cmp_action(data: Data, action: TokenStream) -> TokenStream{
195    let Data::Struct(ref data) = data else { unimplemented!() };
196    let Fields::Named(ref fields) = data.fields else { unimplemented!() };
197    let recursive = fields.named.iter().map(|f|{
198        let name = &f.ident;
199        quote_spanned! { f.span() => #name: self.#name #action rhs.#name, }
200    });
201    //expands to `Self { v1: self.v1 #action rhs.v1, v2: self.v2 #action rhs.v2, .. }`
202    quote! {
203        Self { #(#recursive)* }
204    }
205}
206
207#[proc_macro_derive(CmpOps)]
208pub fn cmp_ops(item: proc_macro::TokenStream) -> proc_macro::TokenStream{
209    let mut result: proc_macro::TokenStream = quote! {}.into();
210    result.extend(cmp_add(item.clone()));
211    result.extend(cmp_add_assign(item.clone()));
212    result.extend(cmp_sub(item.clone()));
213    result.extend(cmp_sub_assign(item.clone()));
214    result.extend(cmp_mul(item.clone()));
215    result.extend(cmp_mul_assign(item.clone()));
216    result.extend(cmp_div(item.clone()));
217    result.extend(cmp_div_assign(item.clone()));
218    result.extend(cmp_rem(item.clone()));
219    result.extend(cmp_rem_assign(item.clone()));
220    result.extend(cmp_neg(item));
221    result
222}