Skip to content

Commit

Permalink
adjust definition of Py2Borrowed to enable PyBytes implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
davidhewitt committed Dec 15, 2023
1 parent 41345ed commit d6f18b5
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 11 deletions.
24 changes: 17 additions & 7 deletions src/instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,11 @@ unsafe impl<T> 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<ffi::PyObject>, PhantomData<&'a Py2<'py, T>>); // TODO is it useful to have the generic form?
pub(crate) struct Py2Borrowed<'a, 'py, T>(
NonNull<ffi::PyObject>,
PhantomData<&'a Py<T>>,
Python<'py>,
); // TODO is it useful to have the generic form?

impl<'a, 'py> Py2Borrowed<'a, 'py, PyAny> {
/// # Safety
Expand All @@ -241,18 +245,18 @@ impl<'a, 'py> Py2Borrowed<'a, 'py, PyAny> {
py: Python<'py>,
ptr: *mut ffi::PyObject,
) -> PyResult<Self> {
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<Self> {
NonNull::new(ptr).map(|ptr| Self(ptr, PhantomData))
pub(crate) unsafe fn from_ptr_or_opt(py: Python<'py>, ptr: *mut ffi::PyObject) -> Option<Self> {
NonNull::new(ptr).map(|ptr| Self(ptr, PhantomData, py))
}

/// # Safety
Expand All @@ -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,
)
}
}
Expand All @@ -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(),
)
}
}
Expand Down Expand Up @@ -852,6 +858,10 @@ impl<T> Py<T> {
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).
///
Expand Down
6 changes: 2 additions & 4 deletions src/types/bytes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,10 +127,8 @@ impl Py<PyBytes> {
/// 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()
}
}

Expand Down

0 comments on commit d6f18b5

Please sign in to comment.