You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
rust-pyo3_0.19/SOURCES/0001-backport-support-for-P...

165 lines
6.8 KiB

From 13590693f15bdc8208e448adf1da5b828331aaac Mon Sep 17 00:00:00 2001
From: Fabio Valentini <decathorpe@gmail.com>
Date: Wed, 26 Jun 2024 19:58:54 +0200
Subject: [PATCH] backport support for Python 3.13
---
src/conversions/std/num.rs | 113 ++++++++++++++++++++++++++++---------
1 file changed, 87 insertions(+), 26 deletions(-)
diff --git a/src/conversions/std/num.rs b/src/conversions/std/num.rs
index 3427942..9dd93cf 100644
--- a/src/conversions/std/num.rs
+++ b/src/conversions/std/num.rs
@@ -5,6 +5,8 @@ use crate::{
ToPyObject,
};
use std::convert::TryFrom;
+#[cfg(Py_3_13)]
+use std::convert::TryInto;
use std::num::{
NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroIsize, NonZeroU128,
NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize,
@@ -169,7 +171,7 @@ mod fast_128bit_int_conversion {
// for 128bit Integers
macro_rules! int_convert_128 {
- ($rust_type: ty, $is_signed: expr) => {
+ ($rust_type: ty, $is_signed: literal) => {
impl ToPyObject for $rust_type {
#[inline]
fn to_object(&self, py: Python<'_>) -> PyObject {
@@ -178,18 +180,47 @@ mod fast_128bit_int_conversion {
}
impl IntoPy<PyObject> for $rust_type {
fn into_py(self, py: Python<'_>) -> PyObject {
- // Always use little endian
- let bytes = self.to_le_bytes();
- unsafe {
- PyObject::from_owned_ptr(
- py,
- ffi::_PyLong_FromByteArray(
- bytes.as_ptr() as *const std::os::raw::c_uchar,
- bytes.len(),
- 1,
- $is_signed,
- ),
- )
+ #[cfg(not(Py_3_13))]
+ {
+ let bytes = self.to_le_bytes();
+ unsafe {
+ PyObject::from_owned_ptr(
+ py,
+ ffi::_PyLong_FromByteArray(
+ bytes.as_ptr().cast(),
+ bytes.len(),
+ 1,
+ $is_signed.into(),
+ ),
+ )
+ }
+ }
+ #[cfg(Py_3_13)]
+ {
+ let bytes = self.to_ne_bytes();
+ if $is_signed {
+ unsafe {
+ PyObject::from_owned_ptr(
+ py,
+ ffi::PyLong_FromNativeBytes(
+ bytes.as_ptr().cast(),
+ bytes.len(),
+ ffi::Py_ASNATIVEBYTES_NATIVE_ENDIAN,
+ ),
+ )
+ }
+ } else {
+ unsafe {
+ PyObject::from_owned_ptr(
+ py,
+ ffi::PyLong_FromUnsignedNativeBytes(
+ bytes.as_ptr().cast(),
+ bytes.len(),
+ ffi::Py_ASNATIVEBYTES_NATIVE_ENDIAN,
+ ),
+ )
+ }
+ }
}
}
@@ -204,17 +235,47 @@ mod fast_128bit_int_conversion {
let num = unsafe {
PyObject::from_owned_ptr_or_err(ob.py(), ffi::PyNumber_Index(ob.as_ptr()))?
};
- let mut buffer = [0; std::mem::size_of::<$rust_type>()];
- crate::err::error_on_minusone(ob.py(), unsafe {
- ffi::_PyLong_AsByteArray(
- num.as_ptr() as *mut ffi::PyLongObject,
- buffer.as_mut_ptr(),
- buffer.len(),
- 1,
- $is_signed,
- )
- })?;
- Ok(<$rust_type>::from_le_bytes(buffer))
+ let mut buffer = [0u8; std::mem::size_of::<$rust_type>()];
+ #[cfg(not(Py_3_13))]
+ {
+ crate::err::error_on_minusone(ob.py(), unsafe {
+ ffi::_PyLong_AsByteArray(
+ num.as_ptr() as *mut ffi::PyLongObject,
+ buffer.as_mut_ptr(),
+ buffer.len(),
+ 1,
+ $is_signed.into(),
+ )
+ })?;
+ Ok(<$rust_type>::from_le_bytes(buffer))
+ }
+ #[cfg(Py_3_13)]
+ {
+ let mut flags = ffi::Py_ASNATIVEBYTES_NATIVE_ENDIAN;
+ if !$is_signed {
+ flags |= ffi::Py_ASNATIVEBYTES_UNSIGNED_BUFFER
+ | ffi::Py_ASNATIVEBYTES_REJECT_NEGATIVE;
+ }
+ let actual_size: usize = unsafe {
+ ffi::PyLong_AsNativeBytes(
+ num.as_ptr(),
+ buffer.as_mut_ptr().cast(),
+ buffer
+ .len()
+ .try_into()
+ .expect("length of buffer fits in Py_ssize_t"),
+ flags,
+ )
+ }
+ .try_into()
+ .map_err(|_| PyErr::fetch(ob.py()))?;
+ if actual_size as usize > buffer.len() {
+ return Err(crate::exceptions::PyOverflowError::new_err(
+ "Python int larger than 128 bits",
+ ));
+ }
+ Ok(<$rust_type>::from_ne_bytes(buffer))
+ }
}
#[cfg(feature = "experimental-inspect")]
@@ -225,8 +286,8 @@ mod fast_128bit_int_conversion {
};
}
- int_convert_128!(i128, 1);
- int_convert_128!(u128, 0);
+ int_convert_128!(i128, true);
+ int_convert_128!(u128, false);
}
// For ABI3 we implement the conversion manually.
--
2.45.2