@@ -217,6 +217,96 @@ unsafe impl<T> AsPyPointer for Py2<'_, T> {
217
217
}
218
218
}
219
219
220
+ /// A borrowed equivalent to `Py2`.
221
+ ///
222
+ /// The advantage of this over `&Py2` is that it avoids the need to have a pointer-to-pointer, as Py2
223
+ /// is already a pointer to an `ffi::PyObject``.
224
+ #[ repr( transparent) ]
225
+ pub ( crate ) struct Py2Borrowed < ' a , ' py , T > (
226
+ NonNull < ffi:: PyObject > ,
227
+ PhantomData < & ' a Py < T > > ,
228
+ Python < ' py > ,
229
+ ) ;
230
+
231
+ impl < ' a , ' py > Py2Borrowed < ' a , ' py , PyAny > {
232
+ /// # Safety
233
+ /// This is similar to `std::slice::from_raw_parts`, the lifetime `'a` is completely defined by
234
+ /// the caller and it's the caller's responsibility to ensure that the reference this is
235
+ /// derived from is valid for the lifetime `'a`.
236
+ pub ( crate ) unsafe fn from_ptr_or_err (
237
+ py : Python < ' py > ,
238
+ ptr : * mut ffi:: PyObject ,
239
+ ) -> PyResult < Self > {
240
+ NonNull :: new ( ptr) . map_or_else (
241
+ || Err ( PyErr :: fetch ( py) ) ,
242
+ |ptr| Ok ( Self ( ptr, PhantomData , py) ) ,
243
+ )
244
+ }
245
+
246
+ /// # Safety
247
+ /// This is similar to `std::slice::from_raw_parts`, the lifetime `'a` is completely defined by
248
+ /// the caller and it's the caller's responsibility to ensure that the reference this is
249
+ /// derived from is valid for the lifetime `'a`.
250
+ pub ( crate ) unsafe fn from_ptr_or_opt ( py : Python < ' py > , ptr : * mut ffi:: PyObject ) -> Option < Self > {
251
+ NonNull :: new ( ptr) . map ( |ptr| Self ( ptr, PhantomData , py) )
252
+ }
253
+
254
+ /// # Safety
255
+ /// This is similar to `std::slice::from_raw_parts`, the lifetime `'a` is completely defined by
256
+ /// the caller and it's the caller's responsibility to ensure that the reference this is
257
+ /// derived from is valid for the lifetime `'a`.
258
+ pub ( crate ) unsafe fn from_ptr ( py : Python < ' py > , ptr : * mut ffi:: PyObject ) -> Self {
259
+ Self (
260
+ NonNull :: new ( ptr) . unwrap_or_else ( || crate :: err:: panic_after_error ( py) ) ,
261
+ PhantomData ,
262
+ py,
263
+ )
264
+ }
265
+ }
266
+
267
+ impl < ' a , ' py , T > From < & ' a Py2 < ' py , T > > for Py2Borrowed < ' a , ' py , T > {
268
+ /// Create borrow on a Py2
269
+ fn from ( instance : & ' a Py2 < ' py , T > ) -> Self {
270
+ Self (
271
+ unsafe { NonNull :: new_unchecked ( instance. as_ptr ( ) ) } ,
272
+ PhantomData ,
273
+ instance. py ( ) ,
274
+ )
275
+ }
276
+ }
277
+
278
+ impl < ' py , T > Py2Borrowed < ' py , ' py , T >
279
+ where
280
+ T : HasPyGilRef ,
281
+ {
282
+ pub ( crate ) fn from_gil_ref ( gil_ref : & ' py T :: AsRefTarget ) -> Self {
283
+ // Safety: &'py T::AsRefTarget is expected to be a Python pointer,
284
+ // so &'py T::AsRefTarget has the same layout as Self.
285
+ unsafe { std:: mem:: transmute ( gil_ref) }
286
+ }
287
+
288
+ // pub(crate) fn into_gil_ref(self) -> &'py T::AsRefTarget {
289
+ // // Safety: self is a borrow over `'py`.
290
+ // unsafe { self.py().from_borrowed_ptr(self.0.as_ptr()) }
291
+ // }
292
+ }
293
+
294
+ impl < T > std:: fmt:: Debug for Py2Borrowed < ' _ , ' _ , T > {
295
+ fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
296
+ Py2 :: fmt ( self , f)
297
+ }
298
+ }
299
+
300
+ impl < ' py , T > Deref for Py2Borrowed < ' _ , ' py , T > {
301
+ type Target = Py2 < ' py , T > ;
302
+
303
+ #[ inline]
304
+ fn deref ( & self ) -> & Py2 < ' py , T > {
305
+ // safety: Py2 has the same layout as NonNull<ffi::PyObject>
306
+ unsafe { & * ( & self . 0 as * const _ as * const Py2 < ' py , T > ) }
307
+ }
308
+ }
309
+
220
310
/// A GIL-independent reference to an object allocated on the Python heap.
221
311
///
222
312
/// This type does not auto-dereference to the inner object because you must prove you hold the GIL to access it.
@@ -727,6 +817,10 @@ impl<T> Py<T> {
727
817
Py2 ( py, ManuallyDrop :: new ( self ) )
728
818
}
729
819
820
+ pub ( crate ) fn attach_borrow < ' a , ' py > ( & ' a self , py : Python < ' py > ) -> Py2Borrowed < ' a , ' py , T > {
821
+ Py2Borrowed ( self . 0 , PhantomData , py)
822
+ }
823
+
730
824
/// Returns whether `self` and `other` point to the same object. To compare
731
825
/// the equality of two objects (the `==` operator), use [`eq`](PyAny::eq).
732
826
///
0 commit comments