Skip to content

Commit d6f18b5

Browse files
committed
adjust definition of Py2Borrowed to enable PyBytes implementation
1 parent 41345ed commit d6f18b5

File tree

2 files changed

+19
-11
lines changed

2 files changed

+19
-11
lines changed

src/instance.rs

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,11 @@ unsafe impl<T> AsPyPointer for Py2<'_, T> {
230230
/// The advantage of this over `&Py2` is that it avoids the need to have a pointer-to-pointer, as Py2
231231
/// is already a pointer to a PyObject.
232232
#[repr(transparent)]
233-
pub(crate) struct Py2Borrowed<'a, 'py, T>(NonNull<ffi::PyObject>, PhantomData<&'a Py2<'py, T>>); // TODO is it useful to have the generic form?
233+
pub(crate) struct Py2Borrowed<'a, 'py, T>(
234+
NonNull<ffi::PyObject>,
235+
PhantomData<&'a Py<T>>,
236+
Python<'py>,
237+
); // TODO is it useful to have the generic form?
234238

235239
impl<'a, 'py> Py2Borrowed<'a, 'py, PyAny> {
236240
/// # Safety
@@ -241,18 +245,18 @@ impl<'a, 'py> Py2Borrowed<'a, 'py, PyAny> {
241245
py: Python<'py>,
242246
ptr: *mut ffi::PyObject,
243247
) -> PyResult<Self> {
244-
NonNull::new(ptr).map_or_else(|| Err(PyErr::fetch(py)), |ptr| Ok(Self(ptr, PhantomData)))
248+
NonNull::new(ptr).map_or_else(
249+
|| Err(PyErr::fetch(py)),
250+
|ptr| Ok(Self(ptr, PhantomData, py)),
251+
)
245252
}
246253

247254
/// # Safety
248255
/// This is similar to `std::slice::from_raw_parts`, the lifetime `'a` is completely defined by
249256
/// the caller and it's the caller's responsibility to ensure that the reference this is
250257
/// derived from is valid for the lifetime `'a`.
251-
pub(crate) unsafe fn from_ptr_or_opt(
252-
_py: Python<'py>,
253-
ptr: *mut ffi::PyObject,
254-
) -> Option<Self> {
255-
NonNull::new(ptr).map(|ptr| Self(ptr, PhantomData))
258+
pub(crate) unsafe fn from_ptr_or_opt(py: Python<'py>, ptr: *mut ffi::PyObject) -> Option<Self> {
259+
NonNull::new(ptr).map(|ptr| Self(ptr, PhantomData, py))
256260
}
257261

258262
/// # Safety
@@ -263,6 +267,7 @@ impl<'a, 'py> Py2Borrowed<'a, 'py, PyAny> {
263267
Self(
264268
NonNull::new(ptr).unwrap_or_else(|| crate::err::panic_after_error(py)),
265269
PhantomData,
270+
py,
266271
)
267272
}
268273
}
@@ -273,6 +278,7 @@ impl<'a, 'py, T> From<&'a Py2<'py, T>> for Py2Borrowed<'a, 'py, T> {
273278
Self(
274279
unsafe { NonNull::new_unchecked(instance.as_ptr()) },
275280
PhantomData,
281+
instance.py(),
276282
)
277283
}
278284
}
@@ -852,6 +858,10 @@ impl<T> Py<T> {
852858
Py2(py, ManuallyDrop::new(self))
853859
}
854860

861+
pub(crate) fn attach_borrow<'a, 'py>(&'a self, py: Python<'py>) -> Py2Borrowed<'a, 'py, T> {
862+
Py2Borrowed(self.0, PhantomData, py)
863+
}
864+
855865
/// Returns whether `self` and `other` point to the same object. To compare
856866
/// the equality of two objects (the `==` operator), use [`eq`](PyAny::eq).
857867
///

src/types/bytes.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -127,10 +127,8 @@ impl Py<PyBytes> {
127127
/// Gets the Python bytes as a byte slice. Because Python bytes are
128128
/// immutable, the result may be used for as long as the reference to
129129
/// `self` is held, including when the GIL is released.
130-
pub fn as_bytes<'a>(&'a self, _py: Python<'_>) -> &'a [u8] {
131-
// Safety: `Py2Borrowed` has the same layout as `Py`
132-
let borrowed: Py2Borrowed<'a, '_, PyBytes> = unsafe { std::mem::transmute_copy(self) };
133-
borrowed.as_bytes()
130+
pub fn as_bytes<'a>(&'a self, py: Python<'_>) -> &'a [u8] {
131+
self.attach_borrow(py).as_bytes()
134132
}
135133
}
136134

0 commit comments

Comments
 (0)