1use crate::conversion::private::Reference;
2use crate::conversion::IntoPyObject;
3use crate::ffi_ptr_ext::FfiPtrExt;
4#[cfg(feature = "experimental-inspect")]
5use crate::inspect::types::TypeInfo;
6use crate::types::any::PyAnyMethods;
7use crate::types::{PyBytes, PyInt};
8use crate::{exceptions, ffi, Bound, FromPyObject, PyAny, PyErr, PyObject, PyResult, Python};
9#[allow(deprecated)]
10use crate::{IntoPy, ToPyObject};
11use std::convert::Infallible;
12use std::num::{
13 NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroIsize, NonZeroU128,
14 NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize,
15};
16use std::os::raw::c_long;
17
18macro_rules! int_fits_larger_int {
19 ($rust_type:ty, $larger_type:ty) => {
20 #[allow(deprecated)]
21 impl ToPyObject for $rust_type {
22 #[inline]
23 fn to_object(&self, py: Python<'_>) -> PyObject {
24 self.into_pyobject(py).unwrap().into_any().unbind()
25 }
26 }
27 #[allow(deprecated)]
28 impl IntoPy<PyObject> for $rust_type {
29 #[inline]
30 fn into_py(self, py: Python<'_>) -> PyObject {
31 self.into_pyobject(py).unwrap().into_any().unbind()
32 }
33 }
34
35 impl<'py> IntoPyObject<'py> for $rust_type {
36 type Target = PyInt;
37 type Output = Bound<'py, Self::Target>;
38 type Error = Infallible;
39
40 fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {
41 (self as $larger_type).into_pyobject(py)
42 }
43
44 #[cfg(feature = "experimental-inspect")]
45 fn type_output() -> TypeInfo {
46 <$larger_type>::type_output()
47 }
48 }
49
50 impl<'py> IntoPyObject<'py> for &$rust_type {
51 type Target = PyInt;
52 type Output = Bound<'py, Self::Target>;
53 type Error = Infallible;
54
55 fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {
56 (*self).into_pyobject(py)
57 }
58
59 #[cfg(feature = "experimental-inspect")]
60 fn type_output() -> TypeInfo {
61 <$larger_type>::type_output()
62 }
63 }
64
65 impl FromPyObject<'_> for $rust_type {
66 fn extract_bound(obj: &Bound<'_, PyAny>) -> PyResult<Self> {
67 let val: $larger_type = obj.extract()?;
68 <$rust_type>::try_from(val)
69 .map_err(|e| exceptions::PyOverflowError::new_err(e.to_string()))
70 }
71
72 #[cfg(feature = "experimental-inspect")]
73 fn type_input() -> TypeInfo {
74 <$larger_type>::type_input()
75 }
76 }
77 };
78}
79
80macro_rules! extract_int {
81 ($obj:ident, $error_val:expr, $pylong_as:expr) => {
82 extract_int!($obj, $error_val, $pylong_as, false)
83 };
84
85 ($obj:ident, $error_val:expr, $pylong_as:expr, $force_index_call: literal) => {
86 if cfg!(Py_3_10) && !$force_index_call {
92 err_if_invalid_value($obj.py(), $error_val, unsafe { $pylong_as($obj.as_ptr()) })
93 } else if let Ok(long) = $obj.downcast::<crate::types::PyInt>() {
94 err_if_invalid_value($obj.py(), $error_val, unsafe { $pylong_as(long.as_ptr()) })
96 } else {
97 unsafe {
98 let num = ffi::PyNumber_Index($obj.as_ptr()).assume_owned_or_err($obj.py())?;
99 err_if_invalid_value($obj.py(), $error_val, $pylong_as(num.as_ptr()))
100 }
101 }
102 };
103}
104
105macro_rules! int_convert_u64_or_i64 {
106 ($rust_type:ty, $pylong_from_ll_or_ull:expr, $pylong_as_ll_or_ull:expr, $force_index_call:literal) => {
107 #[allow(deprecated)]
108 impl ToPyObject for $rust_type {
109 #[inline]
110 fn to_object(&self, py: Python<'_>) -> PyObject {
111 self.into_pyobject(py).unwrap().into_any().unbind()
112 }
113 }
114 #[allow(deprecated)]
115 impl IntoPy<PyObject> for $rust_type {
116 #[inline]
117 fn into_py(self, py: Python<'_>) -> PyObject {
118 self.into_pyobject(py).unwrap().into_any().unbind()
119 }
120 }
121 impl<'py> IntoPyObject<'py> for $rust_type {
122 type Target = PyInt;
123 type Output = Bound<'py, Self::Target>;
124 type Error = Infallible;
125
126 fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {
127 unsafe {
128 Ok($pylong_from_ll_or_ull(self)
129 .assume_owned(py)
130 .downcast_into_unchecked())
131 }
132 }
133
134 #[cfg(feature = "experimental-inspect")]
135 fn type_output() -> TypeInfo {
136 TypeInfo::builtin("int")
137 }
138 }
139 impl<'py> IntoPyObject<'py> for &$rust_type {
140 type Target = PyInt;
141 type Output = Bound<'py, Self::Target>;
142 type Error = Infallible;
143
144 #[inline]
145 fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {
146 (*self).into_pyobject(py)
147 }
148
149 #[cfg(feature = "experimental-inspect")]
150 fn type_output() -> TypeInfo {
151 TypeInfo::builtin("int")
152 }
153 }
154 impl FromPyObject<'_> for $rust_type {
155 fn extract_bound(obj: &Bound<'_, PyAny>) -> PyResult<$rust_type> {
156 extract_int!(obj, !0, $pylong_as_ll_or_ull, $force_index_call)
157 }
158
159 #[cfg(feature = "experimental-inspect")]
160 fn type_input() -> TypeInfo {
161 Self::type_output()
162 }
163 }
164 };
165}
166
167macro_rules! int_fits_c_long {
168 ($rust_type:ty) => {
169 #[allow(deprecated)]
170 impl ToPyObject for $rust_type {
171 #[inline]
172 fn to_object(&self, py: Python<'_>) -> PyObject {
173 self.into_pyobject(py).unwrap().into_any().unbind()
174 }
175 }
176 #[allow(deprecated)]
177 impl IntoPy<PyObject> for $rust_type {
178 #[inline]
179 fn into_py(self, py: Python<'_>) -> PyObject {
180 self.into_pyobject(py).unwrap().into_any().unbind()
181 }
182 }
183
184 impl<'py> IntoPyObject<'py> for $rust_type {
185 type Target = PyInt;
186 type Output = Bound<'py, Self::Target>;
187 type Error = Infallible;
188
189 fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {
190 unsafe {
191 Ok(ffi::PyLong_FromLong(self as c_long)
192 .assume_owned(py)
193 .downcast_into_unchecked())
194 }
195 }
196
197 #[cfg(feature = "experimental-inspect")]
198 fn type_output() -> TypeInfo {
199 TypeInfo::builtin("int")
200 }
201 }
202
203 impl<'py> IntoPyObject<'py> for &$rust_type {
204 type Target = PyInt;
205 type Output = Bound<'py, Self::Target>;
206 type Error = Infallible;
207
208 #[inline]
209 fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {
210 (*self).into_pyobject(py)
211 }
212
213 #[cfg(feature = "experimental-inspect")]
214 fn type_output() -> TypeInfo {
215 TypeInfo::builtin("int")
216 }
217 }
218
219 impl<'py> FromPyObject<'py> for $rust_type {
220 fn extract_bound(obj: &Bound<'_, PyAny>) -> PyResult<Self> {
221 let val: c_long = extract_int!(obj, -1, ffi::PyLong_AsLong)?;
222 <$rust_type>::try_from(val)
223 .map_err(|e| exceptions::PyOverflowError::new_err(e.to_string()))
224 }
225
226 #[cfg(feature = "experimental-inspect")]
227 fn type_input() -> TypeInfo {
228 Self::type_output()
229 }
230 }
231 };
232}
233
234#[allow(deprecated)]
235impl ToPyObject for u8 {
236 #[inline]
237 fn to_object(&self, py: Python<'_>) -> PyObject {
238 self.into_pyobject(py).unwrap().into_any().unbind()
239 }
240}
241#[allow(deprecated)]
242impl IntoPy<PyObject> for u8 {
243 #[inline]
244 fn into_py(self, py: Python<'_>) -> PyObject {
245 self.into_pyobject(py).unwrap().into_any().unbind()
246 }
247}
248impl<'py> IntoPyObject<'py> for u8 {
249 type Target = PyInt;
250 type Output = Bound<'py, Self::Target>;
251 type Error = Infallible;
252
253 fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {
254 unsafe {
255 Ok(ffi::PyLong_FromLong(self as c_long)
256 .assume_owned(py)
257 .downcast_into_unchecked())
258 }
259 }
260
261 #[cfg(feature = "experimental-inspect")]
262 fn type_output() -> TypeInfo {
263 TypeInfo::builtin("int")
264 }
265
266 #[inline]
267 fn owned_sequence_into_pyobject<I>(
268 iter: I,
269 py: Python<'py>,
270 _: crate::conversion::private::Token,
271 ) -> Result<Bound<'py, PyAny>, PyErr>
272 where
273 I: AsRef<[u8]>,
274 {
275 Ok(PyBytes::new(py, iter.as_ref()).into_any())
276 }
277}
278
279impl<'py> IntoPyObject<'py> for &'_ u8 {
280 type Target = PyInt;
281 type Output = Bound<'py, Self::Target>;
282 type Error = Infallible;
283
284 fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {
285 u8::into_pyobject(*self, py)
286 }
287
288 #[cfg(feature = "experimental-inspect")]
289 fn type_output() -> TypeInfo {
290 TypeInfo::builtin("int")
291 }
292
293 #[inline]
294 fn borrowed_sequence_into_pyobject<I>(
295 iter: I,
296 py: Python<'py>,
297 _: crate::conversion::private::Token,
298 ) -> Result<Bound<'py, PyAny>, PyErr>
299 where
300 I: AsRef<[<Self as Reference>::BaseType]>,
302 {
303 Ok(PyBytes::new(py, iter.as_ref()).into_any())
304 }
305}
306
307impl FromPyObject<'_> for u8 {
308 fn extract_bound(obj: &Bound<'_, PyAny>) -> PyResult<Self> {
309 let val: c_long = extract_int!(obj, -1, ffi::PyLong_AsLong)?;
310 u8::try_from(val).map_err(|e| exceptions::PyOverflowError::new_err(e.to_string()))
311 }
312
313 #[cfg(feature = "experimental-inspect")]
314 fn type_input() -> TypeInfo {
315 Self::type_output()
316 }
317}
318
319int_fits_c_long!(i8);
320int_fits_c_long!(i16);
321int_fits_c_long!(u16);
322int_fits_c_long!(i32);
323
324#[cfg(all(target_pointer_width = "64", not(target_os = "windows")))]
326int_fits_c_long!(u32);
327#[cfg(any(target_pointer_width = "32", target_os = "windows"))]
328int_fits_larger_int!(u32, u64);
329
330#[cfg(all(target_pointer_width = "64", not(target_os = "windows")))]
331int_fits_c_long!(i64);
332
333#[cfg(any(target_pointer_width = "32", target_os = "windows"))]
335int_convert_u64_or_i64!(i64, ffi::PyLong_FromLongLong, ffi::PyLong_AsLongLong, false);
336
337#[cfg(all(target_pointer_width = "64", not(target_os = "windows")))]
338int_fits_c_long!(isize);
339#[cfg(any(target_pointer_width = "32", target_os = "windows"))]
340int_fits_larger_int!(isize, i64);
341
342int_fits_larger_int!(usize, u64);
343
344int_convert_u64_or_i64!(
346 u64,
347 ffi::PyLong_FromUnsignedLongLong,
348 ffi::PyLong_AsUnsignedLongLong,
349 true
350);
351
352#[cfg(all(not(Py_LIMITED_API), not(GraalPy)))]
353mod fast_128bit_int_conversion {
354 use super::*;
355
356 macro_rules! int_convert_128 {
358 ($rust_type: ty, $is_signed: literal) => {
359 #[allow(deprecated)]
360 impl ToPyObject for $rust_type {
361 #[inline]
362 fn to_object(&self, py: Python<'_>) -> PyObject {
363 self.into_pyobject(py).unwrap().into_any().unbind()
364 }
365 }
366
367 #[allow(deprecated)]
368 impl IntoPy<PyObject> for $rust_type {
369 #[inline]
370 fn into_py(self, py: Python<'_>) -> PyObject {
371 self.into_pyobject(py).unwrap().into_any().unbind()
372 }
373 }
374
375 impl<'py> IntoPyObject<'py> for $rust_type {
376 type Target = PyInt;
377 type Output = Bound<'py, Self::Target>;
378 type Error = Infallible;
379
380 fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {
381 #[cfg(not(Py_3_13))]
382 {
383 let bytes = self.to_le_bytes();
384 unsafe {
385 Ok(ffi::_PyLong_FromByteArray(
386 bytes.as_ptr().cast(),
387 bytes.len(),
388 1,
389 $is_signed.into(),
390 )
391 .assume_owned(py)
392 .downcast_into_unchecked())
393 }
394 }
395 #[cfg(Py_3_13)]
396 {
397 let bytes = self.to_ne_bytes();
398
399 if $is_signed {
400 unsafe {
401 Ok(ffi::PyLong_FromNativeBytes(
402 bytes.as_ptr().cast(),
403 bytes.len(),
404 ffi::Py_ASNATIVEBYTES_NATIVE_ENDIAN,
405 )
406 .assume_owned(py)
407 .downcast_into_unchecked())
408 }
409 } else {
410 unsafe {
411 Ok(ffi::PyLong_FromUnsignedNativeBytes(
412 bytes.as_ptr().cast(),
413 bytes.len(),
414 ffi::Py_ASNATIVEBYTES_NATIVE_ENDIAN,
415 )
416 .assume_owned(py)
417 .downcast_into_unchecked())
418 }
419 }
420 }
421 }
422
423 #[cfg(feature = "experimental-inspect")]
424 fn type_output() -> TypeInfo {
425 TypeInfo::builtin("int")
426 }
427 }
428
429 impl<'py> IntoPyObject<'py> for &$rust_type {
430 type Target = PyInt;
431 type Output = Bound<'py, Self::Target>;
432 type Error = Infallible;
433
434 #[inline]
435 fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {
436 (*self).into_pyobject(py)
437 }
438
439 #[cfg(feature = "experimental-inspect")]
440 fn type_output() -> TypeInfo {
441 TypeInfo::builtin("int")
442 }
443 }
444
445 impl FromPyObject<'_> for $rust_type {
446 fn extract_bound(ob: &Bound<'_, PyAny>) -> PyResult<$rust_type> {
447 let num =
448 unsafe { ffi::PyNumber_Index(ob.as_ptr()).assume_owned_or_err(ob.py())? };
449 let mut buffer = [0u8; std::mem::size_of::<$rust_type>()];
450 #[cfg(not(Py_3_13))]
451 {
452 crate::err::error_on_minusone(ob.py(), unsafe {
453 ffi::_PyLong_AsByteArray(
454 num.as_ptr() as *mut ffi::PyLongObject,
455 buffer.as_mut_ptr(),
456 buffer.len(),
457 1,
458 $is_signed.into(),
459 )
460 })?;
461 Ok(<$rust_type>::from_le_bytes(buffer))
462 }
463 #[cfg(Py_3_13)]
464 {
465 let mut flags = ffi::Py_ASNATIVEBYTES_NATIVE_ENDIAN;
466 if !$is_signed {
467 flags |= ffi::Py_ASNATIVEBYTES_UNSIGNED_BUFFER
468 | ffi::Py_ASNATIVEBYTES_REJECT_NEGATIVE;
469 }
470 let actual_size: usize = unsafe {
471 ffi::PyLong_AsNativeBytes(
472 num.as_ptr(),
473 buffer.as_mut_ptr().cast(),
474 buffer
475 .len()
476 .try_into()
477 .expect("length of buffer fits in Py_ssize_t"),
478 flags,
479 )
480 }
481 .try_into()
482 .map_err(|_| PyErr::fetch(ob.py()))?;
483 if actual_size as usize > buffer.len() {
484 return Err(crate::exceptions::PyOverflowError::new_err(
485 "Python int larger than 128 bits",
486 ));
487 }
488 Ok(<$rust_type>::from_ne_bytes(buffer))
489 }
490 }
491
492 #[cfg(feature = "experimental-inspect")]
493 fn type_input() -> TypeInfo {
494 Self::type_output()
495 }
496 }
497 };
498 }
499
500 int_convert_128!(i128, true);
501 int_convert_128!(u128, false);
502}
503
504#[cfg(any(Py_LIMITED_API, GraalPy))]
506mod slow_128bit_int_conversion {
507 use super::*;
508 const SHIFT: usize = 64;
509
510 macro_rules! int_convert_128 {
512 ($rust_type: ty, $half_type: ty) => {
513 #[allow(deprecated)]
514 impl ToPyObject for $rust_type {
515 #[inline]
516 fn to_object(&self, py: Python<'_>) -> PyObject {
517 self.into_pyobject(py).unwrap().into_any().unbind()
518 }
519 }
520
521 #[allow(deprecated)]
522 impl IntoPy<PyObject> for $rust_type {
523 #[inline]
524 fn into_py(self, py: Python<'_>) -> PyObject {
525 self.into_pyobject(py).unwrap().into_any().unbind()
526 }
527 }
528
529 impl<'py> IntoPyObject<'py> for $rust_type {
530 type Target = PyInt;
531 type Output = Bound<'py, Self::Target>;
532 type Error = Infallible;
533
534 fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {
535 let lower = (self as u64).into_pyobject(py)?;
536 let upper = ((self >> SHIFT) as $half_type).into_pyobject(py)?;
537 let shift = SHIFT.into_pyobject(py)?;
538 unsafe {
539 let shifted =
540 ffi::PyNumber_Lshift(upper.as_ptr(), shift.as_ptr()).assume_owned(py);
541
542 Ok(ffi::PyNumber_Or(shifted.as_ptr(), lower.as_ptr())
543 .assume_owned(py)
544 .downcast_into_unchecked())
545 }
546 }
547
548 #[cfg(feature = "experimental-inspect")]
549 fn type_output() -> TypeInfo {
550 TypeInfo::builtin("int")
551 }
552 }
553
554 impl<'py> IntoPyObject<'py> for &$rust_type {
555 type Target = PyInt;
556 type Output = Bound<'py, Self::Target>;
557 type Error = Infallible;
558
559 #[inline]
560 fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {
561 (*self).into_pyobject(py)
562 }
563
564 #[cfg(feature = "experimental-inspect")]
565 fn type_output() -> TypeInfo {
566 TypeInfo::builtin("int")
567 }
568 }
569
570 impl FromPyObject<'_> for $rust_type {
571 fn extract_bound(ob: &Bound<'_, PyAny>) -> PyResult<$rust_type> {
572 let py = ob.py();
573 unsafe {
574 let lower = err_if_invalid_value(
575 py,
576 -1 as _,
577 ffi::PyLong_AsUnsignedLongLongMask(ob.as_ptr()),
578 )? as $rust_type;
579 let shift = SHIFT.into_pyobject(py)?;
580 let shifted = PyObject::from_owned_ptr_or_err(
581 py,
582 ffi::PyNumber_Rshift(ob.as_ptr(), shift.as_ptr()),
583 )?;
584 let upper: $half_type = shifted.extract(py)?;
585 Ok((<$rust_type>::from(upper) << SHIFT) | lower)
586 }
587 }
588
589 #[cfg(feature = "experimental-inspect")]
590 fn type_input() -> TypeInfo {
591 Self::type_output()
592 }
593 }
594 };
595 }
596
597 int_convert_128!(i128, i64);
598 int_convert_128!(u128, u64);
599}
600
601fn err_if_invalid_value<T: PartialEq>(
602 py: Python<'_>,
603 invalid_value: T,
604 actual_value: T,
605) -> PyResult<T> {
606 if actual_value == invalid_value {
607 if let Some(err) = PyErr::take(py) {
608 return Err(err);
609 }
610 }
611
612 Ok(actual_value)
613}
614
615macro_rules! nonzero_int_impl {
616 ($nonzero_type:ty, $primitive_type:ty) => {
617 #[allow(deprecated)]
618 impl ToPyObject for $nonzero_type {
619 #[inline]
620 fn to_object(&self, py: Python<'_>) -> PyObject {
621 self.into_pyobject(py).unwrap().into_any().unbind()
622 }
623 }
624
625 #[allow(deprecated)]
626 impl IntoPy<PyObject> for $nonzero_type {
627 #[inline]
628 fn into_py(self, py: Python<'_>) -> PyObject {
629 self.into_pyobject(py).unwrap().into_any().unbind()
630 }
631 }
632
633 impl<'py> IntoPyObject<'py> for $nonzero_type {
634 type Target = PyInt;
635 type Output = Bound<'py, Self::Target>;
636 type Error = Infallible;
637
638 #[inline]
639 fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {
640 self.get().into_pyobject(py)
641 }
642
643 #[cfg(feature = "experimental-inspect")]
644 fn type_output() -> TypeInfo {
645 TypeInfo::builtin("int")
646 }
647 }
648
649 impl<'py> IntoPyObject<'py> for &$nonzero_type {
650 type Target = PyInt;
651 type Output = Bound<'py, Self::Target>;
652 type Error = Infallible;
653
654 #[inline]
655 fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {
656 (*self).into_pyobject(py)
657 }
658
659 #[cfg(feature = "experimental-inspect")]
660 fn type_output() -> TypeInfo {
661 TypeInfo::builtin("int")
662 }
663 }
664
665 impl FromPyObject<'_> for $nonzero_type {
666 fn extract_bound(obj: &Bound<'_, PyAny>) -> PyResult<Self> {
667 let val: $primitive_type = obj.extract()?;
668 <$nonzero_type>::try_from(val)
669 .map_err(|_| exceptions::PyValueError::new_err("invalid zero value"))
670 }
671
672 #[cfg(feature = "experimental-inspect")]
673 fn type_input() -> TypeInfo {
674 <$primitive_type>::type_input()
675 }
676 }
677 };
678}
679
680nonzero_int_impl!(NonZeroI8, i8);
681nonzero_int_impl!(NonZeroI16, i16);
682nonzero_int_impl!(NonZeroI32, i32);
683nonzero_int_impl!(NonZeroI64, i64);
684nonzero_int_impl!(NonZeroI128, i128);
685nonzero_int_impl!(NonZeroIsize, isize);
686nonzero_int_impl!(NonZeroU8, u8);
687nonzero_int_impl!(NonZeroU16, u16);
688nonzero_int_impl!(NonZeroU32, u32);
689nonzero_int_impl!(NonZeroU64, u64);
690nonzero_int_impl!(NonZeroU128, u128);
691nonzero_int_impl!(NonZeroUsize, usize);
692
693#[cfg(test)]
694mod test_128bit_integers {
695 use super::*;
696
697 #[cfg(not(target_arch = "wasm32"))]
698 use crate::types::PyDict;
699
700 #[cfg(not(target_arch = "wasm32"))]
701 use crate::types::dict::PyDictMethods;
702
703 #[cfg(not(target_arch = "wasm32"))]
704 use proptest::prelude::*;
705
706 #[cfg(not(target_arch = "wasm32"))]
707 use std::ffi::CString;
708
709 #[cfg(not(target_arch = "wasm32"))]
710 proptest! {
711 #[test]
712 fn test_i128_roundtrip(x: i128) {
713 Python::with_gil(|py| {
714 let x_py = x.into_pyobject(py).unwrap();
715 let locals = PyDict::new(py);
716 locals.set_item("x_py", &x_py).unwrap();
717 py.run(&CString::new(format!("assert x_py == {}", x)).unwrap(), None, Some(&locals)).unwrap();
718 let roundtripped: i128 = x_py.extract().unwrap();
719 assert_eq!(x, roundtripped);
720 })
721 }
722
723 #[test]
724 fn test_nonzero_i128_roundtrip(
725 x in any::<i128>()
726 .prop_filter("Values must not be 0", |x| x != &0)
727 .prop_map(|x| NonZeroI128::new(x).unwrap())
728 ) {
729 Python::with_gil(|py| {
730 let x_py = x.into_pyobject(py).unwrap();
731 let locals = PyDict::new(py);
732 locals.set_item("x_py", &x_py).unwrap();
733 py.run(&CString::new(format!("assert x_py == {}", x)).unwrap(), None, Some(&locals)).unwrap();
734 let roundtripped: NonZeroI128 = x_py.extract().unwrap();
735 assert_eq!(x, roundtripped);
736 })
737 }
738 }
739
740 #[cfg(not(target_arch = "wasm32"))]
741 proptest! {
742 #[test]
743 fn test_u128_roundtrip(x: u128) {
744 Python::with_gil(|py| {
745 let x_py = x.into_pyobject(py).unwrap();
746 let locals = PyDict::new(py);
747 locals.set_item("x_py", &x_py).unwrap();
748 py.run(&CString::new(format!("assert x_py == {}", x)).unwrap(), None, Some(&locals)).unwrap();
749 let roundtripped: u128 = x_py.extract().unwrap();
750 assert_eq!(x, roundtripped);
751 })
752 }
753
754 #[test]
755 fn test_nonzero_u128_roundtrip(
756 x in any::<u128>()
757 .prop_filter("Values must not be 0", |x| x != &0)
758 .prop_map(|x| NonZeroU128::new(x).unwrap())
759 ) {
760 Python::with_gil(|py| {
761 let x_py = x.into_pyobject(py).unwrap();
762 let locals = PyDict::new(py);
763 locals.set_item("x_py", &x_py).unwrap();
764 py.run(&CString::new(format!("assert x_py == {}", x)).unwrap(), None, Some(&locals)).unwrap();
765 let roundtripped: NonZeroU128 = x_py.extract().unwrap();
766 assert_eq!(x, roundtripped);
767 })
768 }
769 }
770
771 #[test]
772 fn test_i128_max() {
773 Python::with_gil(|py| {
774 let v = i128::MAX;
775 let obj = v.into_pyobject(py).unwrap();
776 assert_eq!(v, obj.extract::<i128>().unwrap());
777 assert_eq!(v as u128, obj.extract::<u128>().unwrap());
778 assert!(obj.extract::<u64>().is_err());
779 })
780 }
781
782 #[test]
783 fn test_i128_min() {
784 Python::with_gil(|py| {
785 let v = i128::MIN;
786 let obj = v.into_pyobject(py).unwrap();
787 assert_eq!(v, obj.extract::<i128>().unwrap());
788 assert!(obj.extract::<i64>().is_err());
789 assert!(obj.extract::<u128>().is_err());
790 })
791 }
792
793 #[test]
794 fn test_u128_max() {
795 Python::with_gil(|py| {
796 let v = u128::MAX;
797 let obj = v.into_pyobject(py).unwrap();
798 assert_eq!(v, obj.extract::<u128>().unwrap());
799 assert!(obj.extract::<i128>().is_err());
800 })
801 }
802
803 #[test]
804 fn test_i128_overflow() {
805 Python::with_gil(|py| {
806 let obj = py.eval(ffi::c_str!("(1 << 130) * -1"), None, None).unwrap();
807 let err = obj.extract::<i128>().unwrap_err();
808 assert!(err.is_instance_of::<crate::exceptions::PyOverflowError>(py));
809 })
810 }
811
812 #[test]
813 fn test_u128_overflow() {
814 Python::with_gil(|py| {
815 let obj = py.eval(ffi::c_str!("1 << 130"), None, None).unwrap();
816 let err = obj.extract::<u128>().unwrap_err();
817 assert!(err.is_instance_of::<crate::exceptions::PyOverflowError>(py));
818 })
819 }
820
821 #[test]
822 fn test_nonzero_i128_max() {
823 Python::with_gil(|py| {
824 let v = NonZeroI128::new(i128::MAX).unwrap();
825 let obj = v.into_pyobject(py).unwrap();
826 assert_eq!(v, obj.extract::<NonZeroI128>().unwrap());
827 assert_eq!(
828 NonZeroU128::new(v.get() as u128).unwrap(),
829 obj.extract::<NonZeroU128>().unwrap()
830 );
831 assert!(obj.extract::<NonZeroU64>().is_err());
832 })
833 }
834
835 #[test]
836 fn test_nonzero_i128_min() {
837 Python::with_gil(|py| {
838 let v = NonZeroI128::new(i128::MIN).unwrap();
839 let obj = v.into_pyobject(py).unwrap();
840 assert_eq!(v, obj.extract::<NonZeroI128>().unwrap());
841 assert!(obj.extract::<NonZeroI64>().is_err());
842 assert!(obj.extract::<NonZeroU128>().is_err());
843 })
844 }
845
846 #[test]
847 fn test_nonzero_u128_max() {
848 Python::with_gil(|py| {
849 let v = NonZeroU128::new(u128::MAX).unwrap();
850 let obj = v.into_pyobject(py).unwrap();
851 assert_eq!(v, obj.extract::<NonZeroU128>().unwrap());
852 assert!(obj.extract::<NonZeroI128>().is_err());
853 })
854 }
855
856 #[test]
857 fn test_nonzero_i128_overflow() {
858 Python::with_gil(|py| {
859 let obj = py.eval(ffi::c_str!("(1 << 130) * -1"), None, None).unwrap();
860 let err = obj.extract::<NonZeroI128>().unwrap_err();
861 assert!(err.is_instance_of::<crate::exceptions::PyOverflowError>(py));
862 })
863 }
864
865 #[test]
866 fn test_nonzero_u128_overflow() {
867 Python::with_gil(|py| {
868 let obj = py.eval(ffi::c_str!("1 << 130"), None, None).unwrap();
869 let err = obj.extract::<NonZeroU128>().unwrap_err();
870 assert!(err.is_instance_of::<crate::exceptions::PyOverflowError>(py));
871 })
872 }
873
874 #[test]
875 fn test_nonzero_i128_zero_value() {
876 Python::with_gil(|py| {
877 let obj = py.eval(ffi::c_str!("0"), None, None).unwrap();
878 let err = obj.extract::<NonZeroI128>().unwrap_err();
879 assert!(err.is_instance_of::<crate::exceptions::PyValueError>(py));
880 })
881 }
882
883 #[test]
884 fn test_nonzero_u128_zero_value() {
885 Python::with_gil(|py| {
886 let obj = py.eval(ffi::c_str!("0"), None, None).unwrap();
887 let err = obj.extract::<NonZeroU128>().unwrap_err();
888 assert!(err.is_instance_of::<crate::exceptions::PyValueError>(py));
889 })
890 }
891}
892
893#[cfg(test)]
894mod tests {
895 use crate::types::PyAnyMethods;
896 use crate::{IntoPyObject, Python};
897 use std::num::*;
898
899 #[test]
900 fn test_u32_max() {
901 Python::with_gil(|py| {
902 let v = u32::MAX;
903 let obj = v.into_pyobject(py).unwrap();
904 assert_eq!(v, obj.extract::<u32>().unwrap());
905 assert_eq!(u64::from(v), obj.extract::<u64>().unwrap());
906 assert!(obj.extract::<i32>().is_err());
907 });
908 }
909
910 #[test]
911 fn test_i64_max() {
912 Python::with_gil(|py| {
913 let v = i64::MAX;
914 let obj = v.into_pyobject(py).unwrap();
915 assert_eq!(v, obj.extract::<i64>().unwrap());
916 assert_eq!(v as u64, obj.extract::<u64>().unwrap());
917 assert!(obj.extract::<u32>().is_err());
918 });
919 }
920
921 #[test]
922 fn test_i64_min() {
923 Python::with_gil(|py| {
924 let v = i64::MIN;
925 let obj = v.into_pyobject(py).unwrap();
926 assert_eq!(v, obj.extract::<i64>().unwrap());
927 assert!(obj.extract::<i32>().is_err());
928 assert!(obj.extract::<u64>().is_err());
929 });
930 }
931
932 #[test]
933 fn test_u64_max() {
934 Python::with_gil(|py| {
935 let v = u64::MAX;
936 let obj = v.into_pyobject(py).unwrap();
937 assert_eq!(v, obj.extract::<u64>().unwrap());
938 assert!(obj.extract::<i64>().is_err());
939 });
940 }
941
942 macro_rules! test_common (
943 ($test_mod_name:ident, $t:ty) => (
944 mod $test_mod_name {
945 use crate::exceptions;
946 use crate::conversion::IntoPyObject;
947 use crate::types::PyAnyMethods;
948 use crate::Python;
949
950 #[test]
951 fn from_py_string_type_error() {
952 Python::with_gil(|py| {
953 let obj = ("123").into_pyobject(py).unwrap();
954 let err = obj.extract::<$t>().unwrap_err();
955 assert!(err.is_instance_of::<exceptions::PyTypeError>(py));
956 });
957 }
958
959 #[test]
960 fn from_py_float_type_error() {
961 Python::with_gil(|py| {
962 let obj = (12.3f64).into_pyobject(py).unwrap();
963 let err = obj.extract::<$t>().unwrap_err();
964 assert!(err.is_instance_of::<exceptions::PyTypeError>(py));});
965 }
966
967 #[test]
968 fn to_py_object_and_back() {
969 Python::with_gil(|py| {
970 let val = 123 as $t;
971 let obj = val.into_pyobject(py).unwrap();
972 assert_eq!(obj.extract::<$t>().unwrap(), val as $t);});
973 }
974 }
975 )
976 );
977
978 test_common!(i8, i8);
979 test_common!(u8, u8);
980 test_common!(i16, i16);
981 test_common!(u16, u16);
982 test_common!(i32, i32);
983 test_common!(u32, u32);
984 test_common!(i64, i64);
985 test_common!(u64, u64);
986 test_common!(isize, isize);
987 test_common!(usize, usize);
988 test_common!(i128, i128);
989 test_common!(u128, u128);
990
991 #[test]
992 fn test_nonzero_u32_max() {
993 Python::with_gil(|py| {
994 let v = NonZeroU32::new(u32::MAX).unwrap();
995 let obj = v.into_pyobject(py).unwrap();
996 assert_eq!(v, obj.extract::<NonZeroU32>().unwrap());
997 assert_eq!(NonZeroU64::from(v), obj.extract::<NonZeroU64>().unwrap());
998 assert!(obj.extract::<NonZeroI32>().is_err());
999 });
1000 }
1001
1002 #[test]
1003 fn test_nonzero_i64_max() {
1004 Python::with_gil(|py| {
1005 let v = NonZeroI64::new(i64::MAX).unwrap();
1006 let obj = v.into_pyobject(py).unwrap();
1007 assert_eq!(v, obj.extract::<NonZeroI64>().unwrap());
1008 assert_eq!(
1009 NonZeroU64::new(v.get() as u64).unwrap(),
1010 obj.extract::<NonZeroU64>().unwrap()
1011 );
1012 assert!(obj.extract::<NonZeroU32>().is_err());
1013 });
1014 }
1015
1016 #[test]
1017 fn test_nonzero_i64_min() {
1018 Python::with_gil(|py| {
1019 let v = NonZeroI64::new(i64::MIN).unwrap();
1020 let obj = v.into_pyobject(py).unwrap();
1021 assert_eq!(v, obj.extract::<NonZeroI64>().unwrap());
1022 assert!(obj.extract::<NonZeroI32>().is_err());
1023 assert!(obj.extract::<NonZeroU64>().is_err());
1024 });
1025 }
1026
1027 #[test]
1028 fn test_nonzero_u64_max() {
1029 Python::with_gil(|py| {
1030 let v = NonZeroU64::new(u64::MAX).unwrap();
1031 let obj = v.into_pyobject(py).unwrap();
1032 assert_eq!(v, obj.extract::<NonZeroU64>().unwrap());
1033 assert!(obj.extract::<NonZeroI64>().is_err());
1034 });
1035 }
1036
1037 macro_rules! test_nonzero_common (
1038 ($test_mod_name:ident, $t:ty) => (
1039 mod $test_mod_name {
1040 use crate::exceptions;
1041 use crate::conversion::IntoPyObject;
1042 use crate::types::PyAnyMethods;
1043 use crate::Python;
1044 use std::num::*;
1045
1046 #[test]
1047 fn from_py_string_type_error() {
1048 Python::with_gil(|py| {
1049 let obj = ("123").into_pyobject(py).unwrap();
1050 let err = obj.extract::<$t>().unwrap_err();
1051 assert!(err.is_instance_of::<exceptions::PyTypeError>(py));
1052 });
1053 }
1054
1055 #[test]
1056 fn from_py_float_type_error() {
1057 Python::with_gil(|py| {
1058 let obj = (12.3f64).into_pyobject(py).unwrap();
1059 let err = obj.extract::<$t>().unwrap_err();
1060 assert!(err.is_instance_of::<exceptions::PyTypeError>(py));});
1061 }
1062
1063 #[test]
1064 fn to_py_object_and_back() {
1065 Python::with_gil(|py| {
1066 let val = <$t>::new(123).unwrap();
1067 let obj = val.into_pyobject(py).unwrap();
1068 assert_eq!(obj.extract::<$t>().unwrap(), val);});
1069 }
1070 }
1071 )
1072 );
1073
1074 test_nonzero_common!(nonzero_i8, NonZeroI8);
1075 test_nonzero_common!(nonzero_u8, NonZeroU8);
1076 test_nonzero_common!(nonzero_i16, NonZeroI16);
1077 test_nonzero_common!(nonzero_u16, NonZeroU16);
1078 test_nonzero_common!(nonzero_i32, NonZeroI32);
1079 test_nonzero_common!(nonzero_u32, NonZeroU32);
1080 test_nonzero_common!(nonzero_i64, NonZeroI64);
1081 test_nonzero_common!(nonzero_u64, NonZeroU64);
1082 test_nonzero_common!(nonzero_isize, NonZeroIsize);
1083 test_nonzero_common!(nonzero_usize, NonZeroUsize);
1084 test_nonzero_common!(nonzero_i128, NonZeroI128);
1085 test_nonzero_common!(nonzero_u128, NonZeroU128);
1086
1087 #[test]
1088 fn test_i64_bool() {
1089 Python::with_gil(|py| {
1090 let obj = true.into_pyobject(py).unwrap();
1091 assert_eq!(1, obj.extract::<i64>().unwrap());
1092 let obj = false.into_pyobject(py).unwrap();
1093 assert_eq!(0, obj.extract::<i64>().unwrap());
1094 })
1095 }
1096
1097 #[test]
1098 fn test_i64_f64() {
1099 Python::with_gil(|py| {
1100 let obj = 12.34f64.into_pyobject(py).unwrap();
1101 let err = obj.extract::<i64>().unwrap_err();
1102 assert!(err.is_instance_of::<crate::exceptions::PyTypeError>(py));
1103 let obj = 12f64.into_pyobject(py).unwrap();
1105 let err = obj.extract::<i64>().unwrap_err();
1106 assert!(err.is_instance_of::<crate::exceptions::PyTypeError>(py));
1107 })
1108 }
1109}