Skip to content

Commit

Permalink
use PyBorrowedDetached to take 'py lifetime out the picture
Browse files Browse the repository at this point in the history
  • Loading branch information
davidhewitt committed Dec 15, 2023
1 parent a3594d8 commit 7cb1da2
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 7 deletions.
26 changes: 26 additions & 0 deletions src/instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use crate::{
PyTypeInfo, Python, ToPyObject,
};
use crate::{gil, PyTypeCheck};
use std::hash::Hasher;
use std::marker::PhantomData;
use std::mem::{self, ManuallyDrop};
use std::ops::Deref;
Expand Down Expand Up @@ -217,6 +218,10 @@ impl<'py, T> Py2<'py, T> {
// the reference count
ManuallyDrop::new(self).1 .0
}

pub(crate) fn detached_borrow<'a>(&'a self) -> PyBorrowedDetached<'a, T> {
self.1.detached_borrow()
}
}

unsafe impl<T> AsPyPointer for Py2<'_, T> {
Expand All @@ -235,6 +240,23 @@ pub(crate) struct Py2Borrowed<'a, 'py, T>(
pub(crate) PhantomData<&'a Py2<'py, T>>,
); // TODO is it useful to have the generic form?

pub(crate) struct PyBorrowedDetached<'a, T>(NonNull<ffi::PyObject>, PhantomData<&'a Py<T>>);

impl<'py, T> PyBorrowedDetached<'py, T>
where
T: HasPyGilRef,
{
pub(crate) fn from_gil_ref(gil_ref: &'py T::AsRefTarget) -> Self {
Self(unsafe { std::mem::transmute(gil_ref) }, PhantomData)
}
}

impl<T> PyBorrowedDetached<'_, T> {
pub(crate) fn as_ptr(&self) -> *mut ffi::PyObject {
self.0.as_ptr()
}
}

impl<'a, 'py> Py2Borrowed<'a, 'py, PyAny> {
/// # Safety
/// This is similar to `std::slice::from_raw_parts`, the lifetime `'a` is completely defined by
Expand Down Expand Up @@ -697,6 +719,10 @@ impl<T> Py<T> {
std::mem::forget(self);
ptr
}

pub(crate) fn detached_borrow<'a>(&'a self) -> PyBorrowedDetached<'a, T> {
PyBorrowedDetached(self.0, PhantomData)
}
}

impl<T> Py<T>
Expand Down
14 changes: 7 additions & 7 deletions src/types/bytes.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::instance::{Py2, Py2Borrowed};
use crate::instance::{Py2, Py2Borrowed, PyBorrowedDetached};
use crate::{ffi, FromPyObject, IntoPy, Py, PyAny, PyResult, Python, ToPyObject};
use std::borrow::Cow;
use std::ops::Index;
Expand Down Expand Up @@ -89,7 +89,7 @@ impl PyBytes {
/// Gets the Python string as a byte slice.
#[inline]
pub fn as_bytes(&self) -> &[u8] {
Py2Borrowed::from_gil_ref(self).as_bytes()
PyBorrowedDetached::from_gil_ref(self).as_bytes(self.py())
}
}

Expand All @@ -107,13 +107,13 @@ pub(crate) trait PyBytesMethods<'py> {
impl<'py> PyBytesMethods<'py> for Py2<'py, PyBytes> {
#[inline]
fn as_bytes(&self) -> &[u8] {
Py2Borrowed::from(self).as_bytes()
self.detached_borrow().as_bytes(self.py())
}
}

impl<'a> Py2Borrowed<'a, '_, PyBytes> {
impl<'a> PyBorrowedDetached<'a, PyBytes> {
/// Gets the Python string as a byte slice.
fn as_bytes(self) -> &'a [u8] {
fn as_bytes(self, _py: Python<'_>) -> &'a [u8] {
unsafe {
let buffer = ffi::PyBytes_AsString(self.as_ptr()) as *const u8;
let length = ffi::PyBytes_Size(self.as_ptr()) as usize;
Expand All @@ -127,8 +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] {
Py2Borrowed(self.as_non_null(), std::marker::PhantomData).as_bytes()
pub fn as_bytes<'a>(&'a self, py: Python<'_>) -> &'a [u8] {
self.detached_borrow().as_bytes(py)
}
}

Expand Down

0 comments on commit 7cb1da2

Please sign in to comment.