Skip to main content

rustpython_vm/builtins/
capsule.rs

1use super::PyType;
2use crate::{
3    AsObject, Context, Py, PyObject, PyPayload, PyResult, VirtualMachine,
4    class::PyClassImpl,
5    types::{Destructor, Representable},
6};
7use core::ffi::{CStr, c_void};
8use core::sync::atomic::AtomicPtr;
9
10// In RustPython, this is a minimal implementation for compatibility.
11#[pyclass(module = false, name = "PyCapsule")]
12#[derive(Debug)]
13pub struct PyCapsule {
14    ptr: AtomicPtr<c_void>,
15    context: AtomicPtr<c_void>,
16    name: Option<&'static CStr>,
17    destructor: Option<unsafe extern "C" fn(_: *mut PyObject)>,
18}
19
20impl PyPayload for PyCapsule {
21    #[inline]
22    fn class(ctx: &Context) -> &'static Py<PyType> {
23        ctx.types.capsule_type
24    }
25}
26
27#[pyclass(with(Representable, Destructor), flags(DISALLOW_INSTANTIATION))]
28impl PyCapsule {
29    pub fn new(
30        ptr: *mut c_void,
31        name: Option<&'static CStr>,
32        destructor: Option<unsafe extern "C" fn(_: *mut PyObject)>,
33    ) -> Self {
34        Self {
35            ptr: ptr.into(),
36            context: core::ptr::null_mut::<c_void>().into(),
37            name,
38            destructor,
39        }
40    }
41
42    pub fn pointer(&self) -> *mut c_void {
43        self.ptr.load(core::sync::atomic::Ordering::Relaxed)
44    }
45
46    pub fn set_pointer(&self, pointer: *mut c_void) {
47        self.ptr
48            .store(pointer, core::sync::atomic::Ordering::Relaxed);
49    }
50
51    pub fn context(&self) -> *mut c_void {
52        self.context.load(core::sync::atomic::Ordering::Relaxed)
53    }
54
55    pub fn set_context(&self, context: *mut c_void) {
56        self.context
57            .store(context, core::sync::atomic::Ordering::Relaxed);
58    }
59
60    pub fn name(&self) -> Option<&CStr> {
61        self.name
62    }
63
64    fn destructor(&self) -> Option<unsafe extern "C" fn(_: *mut PyObject)> {
65        self.destructor
66    }
67}
68
69impl Representable for PyCapsule {
70    #[inline]
71    fn repr_str(_zelf: &Py<Self>, _vm: &crate::VirtualMachine) -> PyResult<String> {
72        Ok("<capsule object>".to_string())
73    }
74}
75
76impl Destructor for PyCapsule {
77    fn del(zelf: &Py<Self>, _vm: &VirtualMachine) -> PyResult<()> {
78        if zelf.pointer().is_null() {
79            return Ok(());
80        }
81        if let Some(destructor) = zelf.destructor() {
82            unsafe { destructor(zelf.as_object().as_raw().cast_mut()) };
83        }
84        Ok(())
85    }
86}
87
88pub(crate) fn init(context: &'static Context) {
89    PyCapsule::extend_class(context, context.types.capsule_type);
90}