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.
165 lines
6.8 KiB
165 lines
6.8 KiB
2 weeks ago
|
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
|
||
|
|