1use super::any::PyAnyMethods;
2use crate::{ffi, instance::Bound, IntoPyObject, PyAny, Python};
3#[cfg(RustPython)]
4use crate::{
5 sync::PyOnceLock,
6 types::{PyType, PyTypeMethods},
7 Py,
8};
9use core::convert::Infallible;
10
11#[repr(transparent)]
20pub struct PyInt(PyAny);
21
22#[cfg(not(RustPython))]
23pyobject_native_type_core!(PyInt, pyobject_native_static_type_object!(ffi::PyLong_Type), "builtins", "int", #checkfunction=ffi::PyLong_Check);
24
25#[cfg(RustPython)]
26pyobject_native_type_core!(
27 PyInt,
28 |py| {
29 static TYPE: PyOnceLock<Py<PyType>> = PyOnceLock::new();
30 TYPE.import(py, "builtins", "int").unwrap().as_type_ptr()
31 },
32 "builtins",
33 "int",
34 #checkfunction=ffi::PyLong_Check
35);
36
37impl PyInt {
38 pub fn new<'a, T>(py: Python<'a>, i: T) -> Bound<'a, PyInt>
42 where
43 T: IntoPyObject<'a, Target = PyInt, Output = Bound<'a, PyInt>, Error = Infallible>,
44 {
45 match T::into_pyobject(i, py) {
46 Ok(v) => v,
47 Err(never) => match never {},
48 }
49 }
50}
51
52macro_rules! int_compare {
53 ($rust_type: ty) => {
54 impl PartialEq<$rust_type> for Bound<'_, PyInt> {
55 #[inline]
56 fn eq(&self, other: &$rust_type) -> bool {
57 if let Ok(value) = self.extract::<$rust_type>() {
58 value == *other
59 } else {
60 false
61 }
62 }
63 }
64 impl PartialEq<Bound<'_, PyInt>> for $rust_type {
65 #[inline]
66 fn eq(&self, other: &Bound<'_, PyInt>) -> bool {
67 if let Ok(value) = other.extract::<$rust_type>() {
68 value == *self
69 } else {
70 false
71 }
72 }
73 }
74 };
75}
76
77int_compare!(i8);
78int_compare!(u8);
79int_compare!(i16);
80int_compare!(u16);
81int_compare!(i32);
82int_compare!(u32);
83int_compare!(i64);
84int_compare!(u64);
85int_compare!(i128);
86int_compare!(u128);
87int_compare!(isize);
88int_compare!(usize);
89
90#[cfg(test)]
91mod tests {
92 use super::*;
93 use crate::{IntoPyObject, Python};
94
95 #[test]
96 fn test_partial_eq() {
97 Python::attach(|py| {
98 let v_i8 = 123i8;
99 let v_u8 = 123i8;
100 let v_i16 = 123i16;
101 let v_u16 = 123u16;
102 let v_i32 = 123i32;
103 let v_u32 = 123u32;
104 let v_i64 = 123i64;
105 let v_u64 = 123u64;
106 let v_i128 = 123i128;
107 let v_u128 = 123u128;
108 let v_isize = 123isize;
109 let v_usize = 123usize;
110 let obj = 123_i64.into_pyobject(py).unwrap();
111 assert_eq!(v_i8, obj);
112 assert_eq!(obj, v_i8);
113
114 assert_eq!(v_u8, obj);
115 assert_eq!(obj, v_u8);
116
117 assert_eq!(v_i16, obj);
118 assert_eq!(obj, v_i16);
119
120 assert_eq!(v_u16, obj);
121 assert_eq!(obj, v_u16);
122
123 assert_eq!(v_i32, obj);
124 assert_eq!(obj, v_i32);
125
126 assert_eq!(v_u32, obj);
127 assert_eq!(obj, v_u32);
128
129 assert_eq!(v_i64, obj);
130 assert_eq!(obj, v_i64);
131
132 assert_eq!(v_u64, obj);
133 assert_eq!(obj, v_u64);
134
135 assert_eq!(v_i128, obj);
136 assert_eq!(obj, v_i128);
137
138 assert_eq!(v_u128, obj);
139 assert_eq!(obj, v_u128);
140
141 assert_eq!(v_isize, obj);
142 assert_eq!(obj, v_isize);
143
144 assert_eq!(v_usize, obj);
145 assert_eq!(obj, v_usize);
146
147 let big_num = (u8::MAX as u16) + 1;
148 let big_obj = big_num.into_pyobject(py).unwrap();
149
150 for x in 0u8..=u8::MAX {
151 assert_ne!(x, big_obj);
152 assert_ne!(big_obj, x);
153 }
154 });
155 }
156
157 #[test]
158 fn test_display_int() {
159 Python::attach(|py| {
160 let s = PyInt::new(py, 42u8);
161 assert_eq!(format!("{s}"), "42");
162
163 let s = PyInt::new(py, 43i32);
164 assert_eq!(format!("{s}"), "43");
165
166 let s = PyInt::new(py, 44usize);
167 assert_eq!(format!("{s}"), "44");
168 })
169 }
170}