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