1use proc_macro2::{self, TokenStream};
2use quote::{quote, quote_spanned};
3use syn::{parse_macro_input, spanned::Spanned, Data, DeriveInput, Fields};
4#[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#[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#[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#[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#[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#[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#[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#[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#[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#[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#[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 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}