pyo3/types/
num.rs

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