1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
use crate::{ffi, AsPyPointer, PyCell, PyClass, Python};
use std::os::raw::{c_int, c_void};
#[repr(transparent)]
pub struct PyTraverseError(c_int);
pub trait PyGCProtocol<'p>: PyClass {
fn __traverse__(&'p self, visit: PyVisit) -> Result<(), PyTraverseError>;
fn __clear__(&'p mut self);
}
pub trait PyGCTraverseProtocol<'p>: PyGCProtocol<'p> {}
pub trait PyGCClearProtocol<'p>: PyGCProtocol<'p> {}
#[doc(hidden)]
pub unsafe extern "C" fn traverse<T>(
slf: *mut ffi::PyObject,
visit: ffi::visitproc,
arg: *mut c_void,
) -> c_int
where
T: for<'p> PyGCTraverseProtocol<'p>,
{
let pool = crate::GILPool::new();
let py = pool.python();
let slf = py.from_borrowed_ptr::<PyCell<T>>(slf);
let visit = PyVisit {
visit,
arg,
_py: py,
};
let borrow = slf.try_borrow();
if let Ok(borrow) = borrow {
match borrow.__traverse__(visit) {
Ok(()) => 0,
Err(PyTraverseError(code)) => code,
}
} else {
0
}
}
#[doc(hidden)]
pub unsafe extern "C" fn clear<T>(slf: *mut ffi::PyObject) -> c_int
where
T: for<'p> PyGCClearProtocol<'p>,
{
let pool = crate::GILPool::new();
let slf = pool.python().from_borrowed_ptr::<PyCell<T>>(slf);
slf.borrow_mut().__clear__();
0
}
#[derive(Clone)]
pub struct PyVisit<'p> {
visit: ffi::visitproc,
arg: *mut c_void,
_py: Python<'p>,
}
impl<'p> PyVisit<'p> {
pub fn call<T>(&self, obj: &T) -> Result<(), PyTraverseError>
where
T: AsPyPointer,
{
let r = unsafe { (self.visit)(obj.as_ptr(), self.arg) };
if r == 0 {
Ok(())
} else {
Err(PyTraverseError(r))
}
}
}