1use super::any::PyAnyMethods;
2use crate::{ffi, instance::Bound, IntoPyObject, PyAny, Python};
3use std::convert::Infallible;
4
5/// Represents a Python `int` object.
6///
7/// Values of this type are accessed via PyO3's smart pointers, e.g. as
8/// [`Py<PyInt>`][crate::Py] or [`Bound<'py, PyInt>`][crate::Bound].
9///
10/// You can usually avoid directly working with this type
11/// by using [`ToPyObject`](crate::conversion::ToPyObject)
12/// and [`extract`](super::PyAnyMethods::extract)
13/// with the primitive Rust integer types.
14#[repr(transparent)]
15pub struct PyInt(PyAny);
16
17pyobject_native_type_core!(PyInt, pyobject_native_static_type_object!(ffi::PyLong_Type), #checkfunction=ffi::PyLong_Check);
18
19/// Deprecated alias for [`PyInt`].
20#[deprecated(since = "0.23.0", note = "use `PyInt` instead")]
21pub type PyLong = PyInt;
22
23impl PyInt {
24 /// Creates a new Python int object.
25 ///
26 /// Panics if out of memory.
27 pub fn new<'a, T>(py: Python<'a>, i: T) -> Bound<'a, PyInt>
28 where
29 T: IntoPyObject<'a, Target = PyInt, Output = Bound<'a, PyInt>, Error = Infallible>,
30 {
31 match T::into_pyobject(self:i, py) {
32 Ok(v: Bound<'a, PyInt>) => v,
33 Err(never: Infallible) => match never {},
34 }
35 }
36}
37
38macro_rules! int_compare {
39 ($rust_type: ty) => {
40 impl PartialEq<$rust_type> for Bound<'_, PyInt> {
41 #[inline]
42 fn eq(&self, other: &$rust_type) -> bool {
43 if let Ok(value) = self.extract::<$rust_type>() {
44 value == *other
45 } else {
46 false
47 }
48 }
49 }
50 impl PartialEq<Bound<'_, PyInt>> for $rust_type {
51 #[inline]
52 fn eq(&self, other: &Bound<'_, PyInt>) -> bool {
53 if let Ok(value) = other.extract::<$rust_type>() {
54 value == *self
55 } else {
56 false
57 }
58 }
59 }
60 };
61}
62
63int_compare!(i8);
64int_compare!(u8);
65int_compare!(i16);
66int_compare!(u16);
67int_compare!(i32);
68int_compare!(u32);
69int_compare!(i64);
70int_compare!(u64);
71int_compare!(i128);
72int_compare!(u128);
73int_compare!(isize);
74int_compare!(usize);
75
76#[cfg(test)]
77mod tests {
78 use super::*;
79 use crate::{IntoPyObject, Python};
80
81 #[test]
82 fn test_partial_eq() {
83 Python::with_gil(|py| {
84 let v_i8 = 123i8;
85 let v_u8 = 123i8;
86 let v_i16 = 123i16;
87 let v_u16 = 123u16;
88 let v_i32 = 123i32;
89 let v_u32 = 123u32;
90 let v_i64 = 123i64;
91 let v_u64 = 123u64;
92 let v_i128 = 123i128;
93 let v_u128 = 123u128;
94 let v_isize = 123isize;
95 let v_usize = 123usize;
96 let obj = 123_i64.into_pyobject(py).unwrap();
97 assert_eq!(v_i8, obj);
98 assert_eq!(obj, v_i8);
99
100 assert_eq!(v_u8, obj);
101 assert_eq!(obj, v_u8);
102
103 assert_eq!(v_i16, obj);
104 assert_eq!(obj, v_i16);
105
106 assert_eq!(v_u16, obj);
107 assert_eq!(obj, v_u16);
108
109 assert_eq!(v_i32, obj);
110 assert_eq!(obj, v_i32);
111
112 assert_eq!(v_u32, obj);
113 assert_eq!(obj, v_u32);
114
115 assert_eq!(v_i64, obj);
116 assert_eq!(obj, v_i64);
117
118 assert_eq!(v_u64, obj);
119 assert_eq!(obj, v_u64);
120
121 assert_eq!(v_i128, obj);
122 assert_eq!(obj, v_i128);
123
124 assert_eq!(v_u128, obj);
125 assert_eq!(obj, v_u128);
126
127 assert_eq!(v_isize, obj);
128 assert_eq!(obj, v_isize);
129
130 assert_eq!(v_usize, obj);
131 assert_eq!(obj, v_usize);
132
133 let big_num = (u8::MAX as u16) + 1;
134 let big_obj = big_num.into_pyobject(py).unwrap();
135
136 for x in 0u8..=u8::MAX {
137 assert_ne!(x, big_obj);
138 assert_ne!(big_obj, x);
139 }
140 });
141 }
142
143 #[test]
144 fn test_display_int() {
145 Python::with_gil(|py| {
146 let s = PyInt::new(py, 42u8);
147 assert_eq!(format!("{}", s), "42");
148
149 let s = PyInt::new(py, 43i32);
150 assert_eq!(format!("{}", s), "43");
151
152 let s = PyInt::new(py, 44usize);
153 assert_eq!(format!("{}", s), "44");
154 })
155 }
156}
157