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
124macro_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
530macro_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}