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