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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
use libc::{c_int, c_void, size_t};

use crate::object::*;
use crate::pyport::Py_ssize_t;

#[cfg_attr(windows, link(name = "pythonXY"))]
extern "C" {
    #[cfg(not(all(py_sys_config = "Py_DEBUG", not(Py_3_4))))]
    pub fn PyObject_Malloc(size: size_t) -> *mut c_void;
    #[cfg(Py_3_5)]
    pub fn PyObject_Calloc(nelem: size_t, elsize: size_t) -> *mut c_void;
    #[cfg(not(all(py_sys_config = "Py_DEBUG", not(Py_3_4))))]
    pub fn PyObject_Realloc(ptr: *mut c_void, new_size: size_t) -> *mut c_void;
    #[cfg(not(all(py_sys_config = "Py_DEBUG", not(Py_3_4))))]
    pub fn PyObject_Free(ptr: *mut c_void) -> ();

    #[cfg(all(py_sys_config = "Py_DEBUG", not(Py_3_4)))]
    pub fn _PyObject_DebugMalloc(arg1: size_t) -> *mut c_void;
    #[cfg(all(py_sys_config = "Py_DEBUG", not(Py_3_4)))]
    pub fn _PyObject_DebugRealloc(arg1: *mut c_void, arg2: size_t) -> *mut c_void;
    #[cfg(all(py_sys_config = "Py_DEBUG", not(Py_3_4)))]
    pub fn _PyObject_DebugFree(arg1: *mut c_void);

    #[cfg(all(not(Py_LIMITED_API), Py_3_4, not(Py_3_11)))]
    pub fn _Py_GetAllocatedBlocks() -> Py_ssize_t;
    pub fn PyObject_Init(arg1: *mut PyObject, arg2: *mut PyTypeObject) -> *mut PyObject;
    pub fn PyObject_InitVar(
        arg1: *mut PyVarObject,
        arg2: *mut PyTypeObject,
        arg3: Py_ssize_t,
    ) -> *mut PyVarObject;
    pub fn _PyObject_New(arg1: *mut PyTypeObject) -> *mut PyObject;
    pub fn _PyObject_NewVar(arg1: *mut PyTypeObject, arg2: Py_ssize_t) -> *mut PyVarObject;

    pub fn PyGC_Collect() -> Py_ssize_t;
    #[cfg(Py_3_10)]
    pub fn PyGC_Enable() -> c_int;
    #[cfg(Py_3_10)]
    pub fn PyGC_Disable() -> c_int;
    #[cfg(Py_3_10)]
    pub fn PyGC_IsEnabled() -> c_int;
}

#[cfg(all(py_sys_config = "Py_DEBUG", not(Py_3_4)))]
pub use self::_PyObject_DebugFree as PyObject_Free;
#[cfg(all(py_sys_config = "Py_DEBUG", not(Py_3_4)))]
pub use self::_PyObject_DebugMalloc as PyObject_Malloc;
#[cfg(all(py_sys_config = "Py_DEBUG", not(Py_3_4)))]
pub use self::_PyObject_DebugRealloc as PyObject_Realloc;

#[repr(C)]
#[derive(Copy)]
#[cfg(all(not(Py_LIMITED_API), Py_3_4))]
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(all(not(Py_LIMITED_API), Py_3_4))]
impl Clone for PyObjectArenaAllocator {
    #[inline]
    fn clone(&self) -> Self {
        *self
    }
}
#[cfg(all(not(Py_LIMITED_API), Py_3_4))]
impl Default for PyObjectArenaAllocator {
    #[inline]
    fn default() -> Self {
        unsafe { ::core::mem::zeroed() }
    }
}
#[cfg(all(not(Py_LIMITED_API), Py_3_4))]
#[cfg_attr(windows, link(name = "pythonXY"))]
extern "C" {
    pub fn PyObject_GetArenaAllocator(allocator: *mut PyObjectArenaAllocator) -> ();
    pub fn PyObject_SetArenaAllocator(allocator: *mut PyObjectArenaAllocator) -> ();
}

/// Test if a type has a GC head
#[inline(always)]
pub unsafe fn PyType_IS_GC(t: *mut PyTypeObject) -> c_int {
    PyType_HasFeature(t, Py_TPFLAGS_HAVE_GC)
}

/// Test if an object has a GC head
#[inline(always)]
#[cfg(all(not(Py_LIMITED_API), not(Py_3_9)))]
pub unsafe fn PyObject_IS_GC(o: *mut PyObject) -> c_int {
    (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_attr(windows, link(name = "pythonXY"))]
extern "C" {
    #[cfg(all(not(Py_LIMITED_API), Py_3_9))]
    pub fn PyObject_IS_GC(o: *mut PyObject) -> c_int;

    pub fn _PyObject_GC_Resize(arg1: *mut PyVarObject, arg2: Py_ssize_t) -> *mut PyVarObject;

    #[cfg(all(not(Py_LIMITED_API), not(Py_3_11)))]
    pub fn _PyObject_GC_Malloc(size: size_t) -> *mut PyObject;
    #[cfg(all(not(Py_LIMITED_API), Py_3_5, not(Py_3_11)))]
    pub fn _PyObject_GC_Calloc(size: size_t) -> *mut PyObject;
    pub fn _PyObject_GC_New(arg1: *mut PyTypeObject) -> *mut PyObject;
    pub fn _PyObject_GC_NewVar(arg1: *mut PyTypeObject, arg2: Py_ssize_t) -> *mut PyVarObject;
    pub fn PyObject_GC_Track(arg1: *mut c_void) -> ();
    pub fn PyObject_GC_UnTrack(arg1: *mut c_void) -> ();
    pub fn PyObject_GC_Del(arg1: *mut c_void) -> ();

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

/// Test if a type supports weak references
#[inline(always)]
#[cfg(all(not(Py_LIMITED_API), not(Py_3_11)))]
pub unsafe fn PyType_SUPPORTS_WEAKREFS(t: *mut PyTypeObject) -> c_int {
    ((*t).tp_weaklistoffset > 0) as c_int
}

#[inline(always)]
#[cfg(all(not(Py_LIMITED_API), not(Py_3_9)))]
pub unsafe fn PyObject_GET_WEAKREFS_LISTPTR(o: *mut PyObject) -> *mut *mut PyObject {
    let weaklistoffset = (*Py_TYPE(o)).tp_weaklistoffset as isize;
    (o as *mut u8).offset(weaklistoffset) as *mut *mut PyObject
}

#[cfg_attr(windows, link(name = "pythonXY"))]
extern "C" {
    #[cfg(all(not(Py_LIMITED_API), Py_3_11))]
    pub fn PyType_SUPPORTS_WEAKREFS(t: *mut PyTypeObject) -> c_int;
    #[cfg(all(not(Py_LIMITED_API), Py_3_9))]
    pub fn PyObject_GET_WEAKREFS_LISTPTR(o: *mut PyObject) -> *mut *mut PyObject;
}