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 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 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 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}