pyo3/impl_/
coroutine.rs

1use std::{
2    future::Future,
3    ops::{Deref, DerefMut},
4};
5
6use crate::{
7    coroutine::{cancel::ThrowCallback, Coroutine},
8    instance::Bound,
9    pycell::impl_::PyClassBorrowChecker,
10    pyclass::boolean_struct::False,
11    types::{PyAnyMethods, PyString},
12    IntoPyObject, Py, PyAny, PyClass, PyErr, PyResult, Python,
13};
14
15pub fn new_coroutine<'py, F, T, E>(
16    name: &Bound<'py, PyString>,
17    qualname_prefix: Option<&'static str>,
18    throw_callback: Option<ThrowCallback>,
19    future: F,
20) -> Coroutine
21where
22    F: Future<Output = Result<T, E>> + Send + 'static,
23    T: IntoPyObject<'py>,
24    E: Into<PyErr>,
25{
26    Coroutine::new(Some(name.clone()), qualname_prefix, throw_callback, future)
27}
28
29fn get_ptr<T: PyClass>(obj: &Py<T>) -> *mut T {
30    obj.get_class_object().get_ptr()
31}
32
33pub struct RefGuard<T: PyClass>(Py<T>);
34
35impl<T: PyClass> RefGuard<T> {
36    pub fn new(obj: &Bound<'_, PyAny>) -> PyResult<Self> {
37        let bound = obj.downcast::<T>()?;
38        bound.get_class_object().borrow_checker().try_borrow()?;
39        Ok(RefGuard(bound.clone().unbind()))
40    }
41}
42
43impl<T: PyClass> Deref for RefGuard<T> {
44    type Target = T;
45    fn deref(&self) -> &Self::Target {
46        // SAFETY: `RefGuard` has been built from `PyRef` and provides the same guarantees
47        unsafe { &*get_ptr(&self.0) }
48    }
49}
50
51impl<T: PyClass> Drop for RefGuard<T> {
52    fn drop(&mut self) {
53        Python::with_gil(|gil| {
54            self.0
55                .bind(gil)
56                .get_class_object()
57                .borrow_checker()
58                .release_borrow()
59        })
60    }
61}
62
63pub struct RefMutGuard<T: PyClass<Frozen = False>>(Py<T>);
64
65impl<T: PyClass<Frozen = False>> RefMutGuard<T> {
66    pub fn new(obj: &Bound<'_, PyAny>) -> PyResult<Self> {
67        let bound = obj.downcast::<T>()?;
68        bound.get_class_object().borrow_checker().try_borrow_mut()?;
69        Ok(RefMutGuard(bound.clone().unbind()))
70    }
71}
72
73impl<T: PyClass<Frozen = False>> Deref for RefMutGuard<T> {
74    type Target = T;
75    fn deref(&self) -> &Self::Target {
76        // SAFETY: `RefMutGuard` has been built from `PyRefMut` and provides the same guarantees
77        unsafe { &*get_ptr(&self.0) }
78    }
79}
80
81impl<T: PyClass<Frozen = False>> DerefMut for RefMutGuard<T> {
82    fn deref_mut(&mut self) -> &mut Self::Target {
83        // SAFETY: `RefMutGuard` has been built from `PyRefMut` and provides the same guarantees
84        unsafe { &mut *get_ptr(&self.0) }
85    }
86}
87
88impl<T: PyClass<Frozen = False>> Drop for RefMutGuard<T> {
89    fn drop(&mut self) {
90        Python::with_gil(|gil| {
91            self.0
92                .bind(gil)
93                .get_class_object()
94                .borrow_checker()
95                .release_borrow_mut()
96        })
97    }
98}
⚠️ Internal Docs ⚠️ Not Public API 👉 Official Docs Here