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
151macro_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
557macro_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}