pyderive_macros/
lib.rs

1use syn::{parse_macro_input, DeriveInput};
2
3mod attr;
4mod common;
5mod internal;
6
7#[proc_macro_derive(PyRepr, attributes(pyderive))]
8pub fn py_repr(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
9    let input = parse_macro_input!(input as DeriveInput);
10    match internal::repr::implementation(input) {
11        Ok(r) => r,
12        Err(e) => e.into_compile_error().into(),
13    }
14}
15
16#[proc_macro_derive(PyStr, attributes(pyderive))]
17pub fn py_str(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
18    let input = parse_macro_input!(input as DeriveInput);
19    match internal::str::implementation(input) {
20        Ok(r) => r,
21        Err(e) => e.into_compile_error().into(),
22    }
23}
24
25#[proc_macro_derive(PyLen, attributes(pyderive))]
26pub fn py_len(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
27    let input = parse_macro_input!(input as DeriveInput);
28    match internal::len::implementation(input) {
29        Ok(r) => r,
30        Err(e) => e.into_compile_error().into(),
31    }
32}
33
34#[proc_macro_derive(PyIter, attributes(pyderive))]
35pub fn py_iter(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
36    let input = parse_macro_input!(input as DeriveInput);
37    match internal::iter::implementation(input) {
38        Ok(r) => r,
39        Err(e) => e.into_compile_error().into(),
40    }
41}
42
43#[proc_macro_derive(PyReversed, attributes(pyderive))]
44pub fn py_reversed(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
45    let input = parse_macro_input!(input as DeriveInput);
46    match internal::reversed::implementation(input) {
47        Ok(r) => r,
48        Err(e) => e.into_compile_error().into(),
49    }
50}
51
52#[proc_macro_derive(PyNew, attributes(pyderive))]
53pub fn py_new(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
54    let input = parse_macro_input!(input as DeriveInput);
55    match internal::new::implementation(input) {
56        Ok(r) => r,
57        Err(e) => e.into_compile_error().into(),
58    }
59}
60
61#[proc_macro_derive(PyEq)]
62pub fn py_eq(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
63    let input = parse_macro_input!(input as DeriveInput);
64    match internal::eq::implementation(input) {
65        Ok(r) => r,
66        Err(e) => e.into_compile_error().into(),
67    }
68}
69
70#[proc_macro_derive(PyOrd)]
71pub fn py_ord(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
72    let input = parse_macro_input!(input as DeriveInput);
73    match internal::ord::implementation(input) {
74        Ok(r) => r,
75        Err(e) => e.into_compile_error().into(),
76    }
77}
78
79#[proc_macro_derive(PyRichCmp)]
80pub fn py_richcmp(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
81    let input = parse_macro_input!(input as DeriveInput);
82    match internal::richcmp::implementation(input) {
83        Ok(r) => r,
84        Err(e) => e.into_compile_error().into(),
85    }
86}
87
88#[proc_macro_derive(PyMatchArgs, attributes(pyderive))]
89pub fn py_match_args(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
90    let input = parse_macro_input!(input as DeriveInput);
91    match internal::match_args::implementation(input) {
92        Ok(r) => r,
93        Err(e) => e.into_compile_error().into(),
94    }
95}
96
97#[proc_macro_derive(PyDataclassFields, attributes(pyderive))]
98pub fn py_field(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
99    let input = parse_macro_input!(input as DeriveInput);
100    match internal::dataclass_fields::implementation(input) {
101        Ok(r) => r,
102        Err(e) => e.into_compile_error().into(),
103    }
104}
105
106// ops
107
108macro_rules! impl_unary {
109    ($derive:ident, $name:ident, $pyname:ident, $trait:ident::$method:ident) => {
110        #[proc_macro_derive($derive)]
111        pub fn $name(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
112            use quote::quote;
113
114            let input = parse_macro_input!(input as DeriveInput);
115
116            let struct_name = &input.ident;
117
118            let expanded = quote! {
119                #[pymethods]
120                #[automatically_derived]
121                impl #struct_name {
122                    pub fn $pyname(&self) -> <&Self as $trait>::Output {
123                        use ::std::ops::$trait;
124                        $trait::$method(self)
125                    }
126                }
127            };
128
129            expanded.into()
130        }
131    };
132}
133
134macro_rules! impl_binary {
135    ($derive:ident, $name:ident, $pyname:ident, $trait:ident::$method:ident) => {
136        #[proc_macro_derive($derive)]
137        pub fn $name(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
138            use quote::quote;
139
140            let input = parse_macro_input!(input as DeriveInput);
141
142            let struct_name = &input.ident;
143
144            let expanded = quote! {
145                #[pymethods]
146                #[automatically_derived]
147                impl #struct_name {
148                    pub fn $pyname(&self, other: &Self) -> <&Self as $trait<&Self>>::Output {
149                        use ::std::ops::$trait;
150                        $trait::$method(self, other)
151                    }
152                }
153            };
154
155            expanded.into()
156        }
157    };
158}
159
160macro_rules! impl_reflected_binary {
161    ($derive:ident, $name:ident, $pyname:ident, $trait:ident::$method:ident) => {
162        #[proc_macro_derive($derive)]
163        pub fn $name(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
164            use quote::quote;
165
166            let input = parse_macro_input!(input as DeriveInput);
167
168            let struct_name = &input.ident;
169
170            let expanded = quote! {
171                #[pymethods]
172                #[automatically_derived]
173                impl #struct_name {
174                    pub fn $pyname(&self, other: &Self) -> <&Self as $trait<&Self>>::Output {
175                        use ::std::ops::$trait;
176                        $trait::$method(other, self)
177                    }
178                }
179            };
180
181            expanded.into()
182        }
183    };
184}
185
186macro_rules! impl_binary_assign {
187    ($derive:ident, $name:ident, $pyname:ident, $trait:ident::$method:ident) => {
188        #[proc_macro_derive($derive)]
189        pub fn $name(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
190            use quote::quote;
191
192            let input = parse_macro_input!(input as DeriveInput);
193
194            let struct_name = &input.ident;
195
196            let expanded = quote! {
197                #[pymethods]
198                #[automatically_derived]
199                impl #struct_name {
200                    pub fn $pyname(&mut self, other: &Self) {
201                        use ::std::ops::$trait;
202                        $trait::$method(self, other);
203                    }
204                }
205            };
206
207            expanded.into()
208        }
209    };
210}
211
212impl_unary!(PyNeg, py_neg, __neg__, Neg::neg);
213impl_unary!(PyInvert, py_invert, __invert__, Not::not);
214
215impl_binary!(PyAdd, py_add, __add__, Add::add);
216impl_binary!(PySub, py_sub, __sub__, Sub::sub);
217impl_binary!(PyMul, py_mul, __mul__, Mul::mul);
218impl_binary!(PyMatMul, py_matmul, __matmul__, Mul::mul);
219impl_binary!(PyTrueDiv, py_truediv, __truediv__, Div::div);
220impl_binary!(PyFloorDiv, py_floordiv, __floordiv__, Div::div);
221impl_binary!(PyMod, py_mod, __mod__, Rem::rem);
222
223impl_binary!(PyLeftShift, py_lshift, __lshift__, Shl::shl);
224impl_binary!(PyRightShift, py_rshift, __rshift__, Shr::shr);
225
226impl_binary!(PyAnd, py_and, __and__, BitAnd::bitand);
227impl_binary!(PyOr, py_or, __or__, BitOr::bitor);
228impl_binary!(PyXor, py_xor, __xor__, BitXor::bitxor);
229
230impl_reflected_binary!(PyReflectedAdd, py_radd, __radd__, Add::add);
231impl_reflected_binary!(PyReflectedSub, py_rsub, __rsub__, Sub::sub);
232impl_reflected_binary!(PyReflectedMul, py_rmul, __rmul__, Mul::mul);
233impl_reflected_binary!(PyReflectedMatMul, py_rmatmul, __rmatmul__, Mul::mul);
234impl_reflected_binary!(PyReflectedTrueDiv, py_rtruediv, __rtruediv__, Div::div);
235impl_reflected_binary!(PyReflectedFloorDiv, py_rfloordiv, __rfloordiv__, Div::div);
236impl_reflected_binary!(PyReflectedMod, py_rmod, __rmod__, Rem::rem);
237
238impl_reflected_binary!(PyReflectedLeftShift, py_rlshift, __rlshift__, Shl::shl);
239impl_reflected_binary!(PyReflectedRightShift, py_rrshift, __rrshift__, Shr::shr);
240
241impl_reflected_binary!(PyReflectedAnd, py_rand, __rand__, BitAnd::bitand);
242impl_reflected_binary!(PyReflectedOr, py_ror, __ror__, BitOr::bitor);
243impl_reflected_binary!(PyReflectedXor, py_rxor, __rxor__, BitXor::bitxor);
244
245impl_binary_assign!(PyAddAssign, py_iadd, __iadd__, AddAssign::add_assign);
246impl_binary_assign!(PySubAssign, py_isub, __isub__, SubAssign::sub_assign);
247impl_binary_assign!(PyMulAssign, py_imul, __imul__, MulAssign::mul_assign);
248impl_binary_assign!(
249    PyMatMulAssign,
250    py_imatmul,
251    __imatmul__,
252    MulAssign::mul_assign
253);
254impl_binary_assign!(
255    PyTrueDivAssign,
256    py_itruediv,
257    __itruediv__,
258    DivAssign::div_assign
259);
260impl_binary_assign!(
261    PyFloorDivAssign,
262    py_ifloordiv,
263    __ifloordiv__,
264    DivAssign::div_assign
265);
266impl_binary_assign!(PyModAssign, py_imod, __imod__, RemAssign::rem_assign);
267
268impl_binary_assign!(
269    PyLeftShiftAssign,
270    py_ilshift,
271    __ilshift__,
272    ShlAssign::shl_assign
273);
274impl_binary_assign!(
275    PyRightShiftAssign,
276    py_irshift,
277    __irshift__,
278    ShrAssign::shr_assign
279);
280
281impl_binary_assign!(PyAndAssign, py_iand, __iand__, BitAndAssign::bitand_assign);
282impl_binary_assign!(PyOrAssign, py_ior, __ior__, BitOrAssign::bitor_assign);
283impl_binary_assign!(PyXorAssign, py_ixor, __ixor__, BitXorAssign::bitxor_assign);
284
285#[proc_macro_derive(PyPos)]
286pub fn py_pos(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
287    use quote::quote;
288
289    let input = parse_macro_input!(input as DeriveInput);
290
291    let struct_name = &input.ident;
292
293    let expanded = quote! {
294        #[pymethods]
295        #[automatically_derived]
296        impl #struct_name {
297            pub fn __pos__<'a>(self_: PyRef<'a, Self>) -> PyRef<'a, Self> {
298                self_
299            }
300        }
301    };
302
303    expanded.into()
304}
305
306#[proc_macro_derive(PyDivMod)]
307pub fn py_divmod(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
308    use quote::quote;
309
310    let input = parse_macro_input!(input as DeriveInput);
311
312    let struct_name = &input.ident;
313
314    let expanded = quote! {
315        #[pymethods]
316        #[automatically_derived]
317        impl #struct_name {
318            pub fn __divmod__(&self, other: &Self) -> (
319                <&Self as Div<&Self>>::Output,
320                <&Self as Rem<&Self>>::Output,
321            ) {
322                use ::std::ops::{Div, Rem};
323                (Div::div(self, other), Rem::rem(self, other))
324            }
325        }
326    };
327
328    expanded.into()
329}
330
331#[proc_macro_derive(PyReflectedDivMod)]
332pub fn py_rdivmod(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
333    use quote::quote;
334
335    let input = parse_macro_input!(input as DeriveInput);
336
337    let struct_name = &input.ident;
338
339    let expanded = quote! {
340        #[pymethods]
341        #[automatically_derived]
342        impl #struct_name {
343            pub fn __rdivmod__(&self, other: &Self) -> (
344                <&Self as Div<&Self>>::Output,
345                <&Self as Rem<&Self>>::Output,
346            ) {
347                use ::std::ops::{Div, Rem};
348                (Div::div(other, self), Rem::rem(other, self))
349            }
350        }
351    };
352
353    expanded.into()
354}
355
356#[proc_macro_derive(PyNumeric)]
357pub fn py_numeric(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
358    use quote::quote;
359
360    let input = parse_macro_input!(input as DeriveInput);
361
362    let struct_name = &input.ident;
363
364    let expanded = quote! {
365        #[pymethods]
366        #[automatically_derived]
367        impl #struct_name {
368            pub fn __pos__<'a>(self_: PyRef<'a, Self>) -> PyRef<'a, Self> {
369                self_
370            }
371
372            pub fn __neg__(&self) -> <&Self as Neg>::Output {
373                use ::std::ops::Neg;
374                Neg::neg(self)
375            }
376
377            pub fn __add__(&self, other: &Self) -> <&Self as Add<&Self>>::Output {
378                use ::std::ops::Add;
379                Add::add(self, other)
380            }
381
382            pub fn __sub__(&self, other: &Self) -> <&Self as Sub<&Self>>::Output {
383                use ::std::ops::Sub;
384                Sub::sub(self, other)
385            }
386
387            pub fn __mul__(&self, other: &Self) -> <&Self as Mul<&Self>>::Output {
388                use ::std::ops::Mul;
389                Mul::mul(self, other)
390            }
391
392            pub fn __truediv__(&self, other: &Self) -> <&Self as Div<&Self>>::Output {
393                use ::std::ops::Div;
394                Div::div(self, other)
395            }
396
397            pub fn __mod__(&self, other: &Self) -> <&Self as Rem<&Self>>::Output {
398                use ::std::ops::Rem;
399                Rem::rem(self, other)
400            }
401
402            pub fn __iadd__(&mut self, other: &Self) {
403                use ::std::ops::AddAssign;
404                AddAssign::add_assign(self, other);
405            }
406
407            pub fn __isub__(&mut self, other: &Self) {
408                use ::std::ops::SubAssign;
409                SubAssign::sub_assign(self, other);
410            }
411
412            pub fn __imul__(&mut self, other: &Self) {
413                use ::std::ops::MulAssign;
414                MulAssign::mul_assign(self, other);
415            }
416
417            pub fn __itruediv__(&mut self, other: &Self) {
418                use ::std::ops::DivAssign;
419                DivAssign::div_assign(self, other);
420            }
421
422            pub fn __imod__(&mut self, other: &Self) {
423                use ::std::ops::RemAssign;
424                RemAssign::rem_assign(self, other);
425            }
426
427            pub fn __divmod__(&self, other: &Self) -> (
428                <&Self as ::std::ops::Div<&Self>>::Output,
429                <&Self as ::std::ops::Rem<&Self>>::Output,
430            ) {
431                use ::std::ops::{Div, Rem};
432                (Div::div(self, other), Rem::rem(self, other))
433            }
434        }
435    };
436
437    expanded.into()
438}
439
440#[proc_macro_derive(PyBitwise)]
441pub fn py_bitwise(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
442    use quote::quote;
443
444    let input = parse_macro_input!(input as DeriveInput);
445
446    let struct_name = &input.ident;
447
448    let expanded = quote! {
449        #[pymethods]
450        #[automatically_derived]
451        impl #struct_name {
452            pub fn __invert__(&self) -> <&Self as Not>::Output {
453                use ::std::ops::Not;
454                Not::not(self)
455            }
456
457            pub fn __and__(&self, other: &Self) -> <&Self as BitAnd<&Self>>::Output {
458                use ::std::ops::BitAnd;
459                BitAnd::bitand(self, other)
460            }
461
462            pub fn __or__(&self, other: &Self) -> <&Self as BitOr<&Self>>::Output {
463                use ::std::ops::BitOr;
464                BitOr::bitor(self, other)
465            }
466
467            pub fn __xor__(&self, other: &Self) -> <&Self as BitXor<&Self>>::Output {
468                use ::std::ops::BitXor;
469                BitXor::bitxor(self, other)
470            }
471
472            pub fn __lshift__(&self, other: &Self) -> <&Self as Shl<&Self>>::Output {
473                use ::std::ops::Shl;
474                Shl::shl(self, other)
475            }
476
477            pub fn __rshift__(&self, other: &Self) -> <&Self as Shr<&Self>>::Output {
478                use ::std::ops::Shr;
479                Shr::shr(self, other)
480            }
481
482            pub fn __iand__(&mut self, other: &Self) {
483                use ::std::ops::BitAndAssign;
484                BitAndAssign::bitand_assign(self, other);
485            }
486
487            pub fn __ior__(&mut self, other: &Self) {
488                use ::std::ops::BitOrAssign;
489                BitOrAssign::bitor_assign(self, other);
490            }
491
492            pub fn __ixor__(&mut self, other: &Self) {
493                use ::std::ops::BitXorAssign;
494                BitXorAssign::bitxor_assign(self, other);
495            }
496
497            pub fn __ilshift__(&mut self, other: &Self) {
498                use ::std::ops::ShlAssign;
499                ShlAssign::shl_assign(self, other);
500            }
501
502            pub fn __irshift__(&mut self, other: &Self) {
503                use ::std::ops::ShrAssign;
504                ShrAssign::shr_assign(self, other);
505            }
506        }
507    };
508
509    expanded.into()
510}
511
512// convert
513
514macro_rules! impl_convert {
515    ($derive:ident, $name:ident, $pyname:ident, $ty:ty) => {
516        #[proc_macro_derive($derive)]
517        pub fn $name(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
518            use quote::quote;
519
520            let input = parse_macro_input!(input as DeriveInput);
521
522            let struct_name = &input.ident;
523
524            let expanded = quote! {
525                #[pymethods]
526                #[automatically_derived]
527                impl #struct_name {
528                    pub fn $pyname(&self) -> $ty {
529                        ::std::convert::Into::into(self)
530                    }
531                }
532            };
533            expanded.into()
534        }
535    };
536}
537
538impl_convert!(PyBool, py_bool, __bool__, bool);
539impl_convert!(PyInt, py_int, __int__, i64);
540impl_convert!(PyIndex, py_index, __index__, isize);
541impl_convert!(PyFloat, py_float, __float__, f64);
542
543#[proc_macro_derive(PyBytes)]
544pub fn py_bytes(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
545    use quote::quote;
546
547    let input = parse_macro_input!(input as DeriveInput);
548
549    let struct_name = &input.ident;
550
551    let expanded = quote! {
552        #[pymethods]
553        #[automatically_derived]
554        impl #struct_name {
555            pub fn __bytes__(&self) -> ::std::borrow::Cow<[::std::primitive::u8]> {
556                ::std::convert::Into::into(self)
557            }
558        }
559    };
560
561    expanded.into()
562}
563
564#[cfg(feature = "num-complex")]
565#[proc_macro_derive(PyComplex)]
566pub fn py_complex(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
567    use quote::quote;
568
569    let input = parse_macro_input!(input as DeriveInput);
570
571    let struct_name = &input.ident;
572
573    let expanded = quote! {
574        #[pymethods]
575        #[automatically_derived]
576        impl #struct_name {
577            pub fn __complex__(&self) -> ::num_complex::Complex64 {
578                ::std::convert::Into::into(self)
579            }
580        }
581    };
582
583    expanded.into()
584}