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