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
106macro_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
512macro_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}