From d6f18b5612ab2873e3abd5d91487d79019918497 Mon Sep 17 00:00:00 2001 From: David Hewitt Date: Fri, 15 Dec 2023 13:20:25 +0000 Subject: [PATCH] adjust definition of Py2Borrowed to enable PyBytes implementation --- src/instance.rs | 24 +++++++++++++++++------- src/types/bytes.rs | 6 ++---- 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/src/instance.rs b/src/instance.rs index 7b97e28f69f..8d854bc8b34 100644 --- a/src/instance.rs +++ b/src/instance.rs @@ -230,7 +230,11 @@ unsafe impl AsPyPointer for Py2<'_, T> { /// The advantage of this over `&Py2` is that it avoids the need to have a pointer-to-pointer, as Py2 /// is already a pointer to a PyObject. #[repr(transparent)] -pub(crate) struct Py2Borrowed<'a, 'py, T>(NonNull, PhantomData<&'a Py2<'py, T>>); // TODO is it useful to have the generic form? +pub(crate) struct Py2Borrowed<'a, 'py, T>( + NonNull, + PhantomData<&'a Py>, + Python<'py>, +); // TODO is it useful to have the generic form? impl<'a, 'py> Py2Borrowed<'a, 'py, PyAny> { /// # Safety @@ -241,18 +245,18 @@ impl<'a, 'py> Py2Borrowed<'a, 'py, PyAny> { py: Python<'py>, ptr: *mut ffi::PyObject, ) -> PyResult { - NonNull::new(ptr).map_or_else(|| Err(PyErr::fetch(py)), |ptr| Ok(Self(ptr, PhantomData))) + NonNull::new(ptr).map_or_else( + || Err(PyErr::fetch(py)), + |ptr| Ok(Self(ptr, PhantomData, py)), + ) } /// # Safety /// This is similar to `std::slice::from_raw_parts`, the lifetime `'a` is completely defined by /// the caller and it's the caller's responsibility to ensure that the reference this is /// derived from is valid for the lifetime `'a`. - pub(crate) unsafe fn from_ptr_or_opt( - _py: Python<'py>, - ptr: *mut ffi::PyObject, - ) -> Option { - NonNull::new(ptr).map(|ptr| Self(ptr, PhantomData)) + pub(crate) unsafe fn from_ptr_or_opt(py: Python<'py>, ptr: *mut ffi::PyObject) -> Option { + NonNull::new(ptr).map(|ptr| Self(ptr, PhantomData, py)) } /// # Safety @@ -263,6 +267,7 @@ impl<'a, 'py> Py2Borrowed<'a, 'py, PyAny> { Self( NonNull::new(ptr).unwrap_or_else(|| crate::err::panic_after_error(py)), PhantomData, + py, ) } } @@ -273,6 +278,7 @@ impl<'a, 'py, T> From<&'a Py2<'py, T>> for Py2Borrowed<'a, 'py, T> { Self( unsafe { NonNull::new_unchecked(instance.as_ptr()) }, PhantomData, + instance.py(), ) } } @@ -852,6 +858,10 @@ impl Py { Py2(py, ManuallyDrop::new(self)) } + pub(crate) fn attach_borrow<'a, 'py>(&'a self, py: Python<'py>) -> Py2Borrowed<'a, 'py, T> { + Py2Borrowed(self.0, PhantomData, py) + } + /// Returns whether `self` and `other` point to the same object. To compare /// the equality of two objects (the `==` operator), use [`eq`](PyAny::eq). /// diff --git a/src/types/bytes.rs b/src/types/bytes.rs index 12089b37d2b..3c5b4ddebb3 100644 --- a/src/types/bytes.rs +++ b/src/types/bytes.rs @@ -127,10 +127,8 @@ impl Py { /// Gets the Python bytes as a byte slice. Because Python bytes are /// immutable, the result may be used for as long as the reference to /// `self` is held, including when the GIL is released. - pub fn as_bytes<'a>(&'a self, _py: Python<'_>) -> &'a [u8] { - // Safety: `Py2Borrowed` has the same layout as `Py` - let borrowed: Py2Borrowed<'a, '_, PyBytes> = unsafe { std::mem::transmute_copy(self) }; - borrowed.as_bytes() + pub fn as_bytes<'a>(&'a self, py: Python<'_>) -> &'a [u8] { + self.attach_borrow(py).as_bytes() } }