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
use libc::size_t;
use std::os::raw::c_int;

#[cfg(not(PyPy))]
use std::os::raw::c_void;

use crate::object::*;

// skipped _PyObject_SIZE
// skipped _PyObject_VAR_SIZE

#[cfg(not(Py_3_11))]
extern "C" {
    pub fn _Py_GetAllocatedBlocks() -> crate::Py_ssize_t;
}

#[cfg(not(PyPy))]
#[repr(C)]
#[derive(Copy, Clone)]
pub struct PyObjectArenaAllocator {
    pub ctx: *mut c_void,
    pub alloc: Option<extern "C" fn(ctx: *mut c_void, size: size_t) -> *mut c_void>,
    pub free: Option<extern "C" fn(ctx: *mut c_void, ptr: *mut c_void, size: size_t)>,
}

#[cfg(not(PyPy))]
impl Default for PyObjectArenaAllocator {
    #[inline]
    fn default() -> Self {
        unsafe { std::mem::zeroed() }
    }
}

extern "C" {
    #[cfg(not(PyPy))]
    pub fn PyObject_GetArenaAllocator(allocator: *mut PyObjectArenaAllocator);
    #[cfg(not(PyPy))]
    pub fn PyObject_SetArenaAllocator(allocator: *mut PyObjectArenaAllocator);

    #[cfg(Py_3_9)]
    pub fn PyObject_IS_GC(o: *mut PyObject) -> c_int;
}

#[inline]
#[cfg(not(Py_3_9))]
pub unsafe fn PyObject_IS_GC(o: *mut PyObject) -> c_int {
    (crate::PyType_IS_GC(Py_TYPE(o)) != 0
        && match (*Py_TYPE(o)).tp_is_gc {
            Some(tp_is_gc) => tp_is_gc(o) != 0,
            None => true,
        }) as c_int
}

#[cfg(not(Py_3_11))]
extern "C" {
    pub fn _PyObject_GC_Malloc(size: size_t) -> *mut PyObject;
    pub fn _PyObject_GC_Calloc(size: size_t) -> *mut PyObject;
}

#[inline]
pub unsafe fn PyType_SUPPORTS_WEAKREFS(t: *mut PyTypeObject) -> c_int {
    ((*t).tp_weaklistoffset > 0) as c_int
}

#[inline]
pub unsafe fn PyObject_GET_WEAKREFS_LISTPTR(o: *mut PyObject) -> *mut *mut PyObject {
    let weaklistoffset = (*Py_TYPE(o)).tp_weaklistoffset;
    o.offset(weaklistoffset) as *mut *mut PyObject
}

// skipped PyUnstable_Object_GC_NewWithExtraData