use crate::pyport::Py_ssize_t;
use crate::PyObject;
#[cfg(all(not(Py_LIMITED_API), py_sys_config = "Py_REF_DEBUG"))]
use std::ffi::c_char;
#[cfg(any(Py_3_12, all(py_sys_config = "Py_REF_DEBUG", not(Py_LIMITED_API))))]
use std::ffi::c_int;
#[cfg(all(Py_3_14, any(not(Py_GIL_DISABLED), target_pointer_width = "32")))]
use std::ffi::c_long;
#[cfg(any(Py_GIL_DISABLED, all(Py_3_12, not(Py_3_14))))]
use std::ffi::c_uint;
#[cfg(all(Py_3_14, not(Py_GIL_DISABLED)))]
use std::ffi::c_ulong;
use std::ptr;
#[cfg(Py_GIL_DISABLED)]
use std::sync::atomic::Ordering::Relaxed;
#[cfg(all(Py_3_14, not(Py_3_15)))]
const _Py_STATICALLY_ALLOCATED_FLAG: c_int = 1 << 7;
#[cfg(Py_3_15)]
pub(crate) const _Py_STATICALLY_ALLOCATED_FLAG: c_int = 1 << 2;
#[cfg(all(Py_3_12, not(Py_3_14)))]
const _Py_IMMORTAL_REFCNT: Py_ssize_t = {
if cfg!(target_pointer_width = "64") {
c_uint::MAX as Py_ssize_t
} else {
(c_uint::MAX >> 2) as Py_ssize_t
}
};
#[cfg(all(Py_3_14, not(Py_GIL_DISABLED)))]
const _Py_IMMORTAL_INITIAL_REFCNT: Py_ssize_t = {
if cfg!(target_pointer_width = "64") {
((3 as c_ulong) << (30 as c_ulong)) as Py_ssize_t
} else {
((5 as c_long) << (28 as c_long)) as Py_ssize_t
}
};
#[cfg(all(Py_3_14, not(Py_GIL_DISABLED)))]
const _Py_STATIC_IMMORTAL_INITIAL_REFCNT: Py_ssize_t = {
if cfg!(target_pointer_width = "64") {
_Py_IMMORTAL_INITIAL_REFCNT
| ((_Py_STATICALLY_ALLOCATED_FLAG as Py_ssize_t) << (32 as Py_ssize_t))
} else {
((7 as c_long) << (28 as c_long)) as Py_ssize_t
}
};
#[cfg(all(Py_3_14, target_pointer_width = "32"))]
const _Py_IMMORTAL_MINIMUM_REFCNT: Py_ssize_t = ((1 as c_long) << (30 as c_long)) as Py_ssize_t;
#[cfg(all(Py_3_14, target_pointer_width = "32"))]
const _Py_STATIC_IMMORTAL_MINIMUM_REFCNT: Py_ssize_t =
((6 as c_long) << (28 as c_long)) as Py_ssize_t;
#[cfg(all(Py_3_14, Py_GIL_DISABLED))]
const _Py_IMMORTAL_INITIAL_REFCNT: Py_ssize_t = c_uint::MAX as Py_ssize_t;
#[cfg(Py_GIL_DISABLED)]
pub(crate) const _Py_IMMORTAL_REFCNT_LOCAL: u32 = u32::MAX;
#[cfg(Py_GIL_DISABLED)]
const _Py_REF_SHARED_SHIFT: isize = 2;
extern_libpython! {
#[cfg(all(Py_3_14, Py_LIMITED_API))]
pub fn Py_REFCNT(ob: *mut PyObject) -> Py_ssize_t;
}
#[cfg(not(all(Py_3_14, Py_LIMITED_API)))]
#[inline]
pub unsafe fn Py_REFCNT(ob: *mut PyObject) -> Py_ssize_t {
#[cfg(Py_GIL_DISABLED)]
{
let local = (*ob).ob_ref_local.load(Relaxed);
if local == _Py_IMMORTAL_REFCNT_LOCAL {
#[cfg(not(Py_3_14))]
return _Py_IMMORTAL_REFCNT;
#[cfg(Py_3_14)]
return _Py_IMMORTAL_INITIAL_REFCNT;
}
let shared = (*ob).ob_ref_shared.load(Relaxed);
local as Py_ssize_t + Py_ssize_t::from(shared >> _Py_REF_SHARED_SHIFT)
}
#[cfg(all(Py_LIMITED_API, Py_3_14))]
{
Py_REFCNT(ob)
}
#[cfg(all(not(Py_GIL_DISABLED), not(all(Py_LIMITED_API, Py_3_14)), Py_3_12))]
{
(*ob).ob_refcnt.ob_refcnt
}
#[cfg(all(not(Py_GIL_DISABLED), not(Py_3_12)))]
{
(*ob).ob_refcnt
}
}
#[cfg(Py_3_12)]
#[inline(always)]
unsafe fn _Py_IsImmortal(op: *mut PyObject) -> c_int {
#[cfg(all(target_pointer_width = "64", not(Py_GIL_DISABLED)))]
{
(((*op).ob_refcnt.ob_refcnt as crate::PY_INT32_T) < 0) as c_int
}
#[cfg(all(target_pointer_width = "32", not(Py_GIL_DISABLED)))]
{
#[cfg(not(Py_3_14))]
{
((*op).ob_refcnt.ob_refcnt == _Py_IMMORTAL_REFCNT) as c_int
}
#[cfg(Py_3_14)]
{
((*op).ob_refcnt.ob_refcnt >= _Py_IMMORTAL_MINIMUM_REFCNT) as c_int
}
}
#[cfg(Py_GIL_DISABLED)]
{
((*op).ob_ref_local.load(Relaxed) == _Py_IMMORTAL_REFCNT_LOCAL) as c_int
}
}
extern_libpython! {
#[cfg(all(py_sys_config = "Py_REF_DEBUG", not(Py_LIMITED_API)))]
fn _Py_NegativeRefcount(filename: *const c_char, lineno: c_int, op: *mut PyObject);
#[cfg(all(Py_3_12, py_sys_config = "Py_REF_DEBUG", not(Py_LIMITED_API)))]
fn _Py_INCREF_IncRefTotal();
#[cfg(all(Py_3_12, py_sys_config = "Py_REF_DEBUG", not(Py_LIMITED_API)))]
fn _Py_DECREF_DecRefTotal();
fn _Py_Dealloc(arg1: *mut PyObject);
pub fn Py_IncRef(o: *mut PyObject);
pub fn Py_DecRef(o: *mut PyObject);
#[cfg(Py_3_10)]
fn _Py_IncRef(o: *mut PyObject);
#[cfg(Py_3_10)]
fn _Py_DecRef(o: *mut PyObject);
}
#[inline(always)]
pub unsafe fn Py_INCREF(op: *mut PyObject) {
#[cfg(any(
Py_GIL_DISABLED,
Py_LIMITED_API,
py_sys_config = "Py_REF_DEBUG",
))]
{
#[cfg(Py_3_10)]
{
_Py_IncRef(op);
}
#[cfg(not(Py_3_10))]
{
Py_IncRef(op);
}
}
#[cfg(not(any(
Py_GIL_DISABLED,
Py_LIMITED_API,
py_sys_config = "Py_REF_DEBUG",
)))]
{
#[cfg(all(Py_3_14, target_pointer_width = "64"))]
{
let cur_refcnt = (*op).ob_refcnt.ob_refcnt;
if (cur_refcnt as i32) < 0 {
return;
}
(*op).ob_refcnt.ob_refcnt = cur_refcnt.wrapping_add(1);
}
#[cfg(all(Py_3_12, not(Py_3_14), target_pointer_width = "64"))]
{
let cur_refcnt = (*op).ob_refcnt.ob_refcnt_split[crate::PY_BIG_ENDIAN];
let new_refcnt = cur_refcnt.wrapping_add(1);
if new_refcnt == 0 {
return;
}
(*op).ob_refcnt.ob_refcnt_split[crate::PY_BIG_ENDIAN] = new_refcnt;
}
#[cfg(all(Py_3_12, target_pointer_width = "32"))]
{
if _Py_IsImmortal(op) != 0 {
return;
}
(*op).ob_refcnt.ob_refcnt += 1
}
#[cfg(not(Py_3_12))]
{
(*op).ob_refcnt += 1
}
}
}
#[inline(always)]
#[cfg_attr(
all(py_sys_config = "Py_REF_DEBUG", Py_3_12, not(Py_LIMITED_API)),
track_caller
)]
pub unsafe fn Py_DECREF(op: *mut PyObject) {
#[cfg(any(
Py_GIL_DISABLED,
Py_LIMITED_API,
all(py_sys_config = "Py_REF_DEBUG", not(Py_3_12)),
))]
{
#[cfg(Py_3_10)]
{
_Py_DecRef(op);
}
#[cfg(not(Py_3_10))]
{
Py_DecRef(op);
}
}
#[cfg(not(any(
Py_GIL_DISABLED,
Py_LIMITED_API,
all(py_sys_config = "Py_REF_DEBUG", not(Py_3_12)),
)))]
{
#[cfg(Py_3_12)]
if _Py_IsImmortal(op) != 0 {
return;
}
#[cfg(py_sys_config = "Py_REF_DEBUG")]
_Py_DECREF_DecRefTotal();
#[cfg(Py_3_12)]
{
(*op).ob_refcnt.ob_refcnt -= 1;
#[cfg(py_sys_config = "Py_REF_DEBUG")]
if (*op).ob_refcnt.ob_refcnt < 0 {
let location = std::panic::Location::caller();
let filename = std::ffi::CString::new(location.file()).unwrap();
_Py_NegativeRefcount(filename.as_ptr(), location.line() as i32, op);
}
if (*op).ob_refcnt.ob_refcnt == 0 {
_Py_Dealloc(op);
}
}
#[cfg(not(Py_3_12))]
{
(*op).ob_refcnt -= 1;
if (*op).ob_refcnt == 0 {
_Py_Dealloc(op);
}
}
}
}
#[inline]
pub unsafe fn Py_CLEAR(op: *mut *mut PyObject) {
let tmp = *op;
if !tmp.is_null() {
*op = ptr::null_mut();
Py_DECREF(tmp);
}
}
#[inline]
pub unsafe fn Py_XINCREF(op: *mut PyObject) {
if !op.is_null() {
Py_INCREF(op)
}
}
#[inline]
pub unsafe fn Py_XDECREF(op: *mut PyObject) {
if !op.is_null() {
Py_DECREF(op)
}
}
extern_libpython! {
#[cfg(all(Py_3_10, Py_LIMITED_API))]
#[cfg_attr(docsrs, doc(cfg(Py_3_10)))]
pub fn Py_NewRef(obj: *mut PyObject) -> *mut PyObject;
#[cfg(all(Py_3_10, Py_LIMITED_API))]
#[cfg_attr(docsrs, doc(cfg(Py_3_10)))]
pub fn Py_XNewRef(obj: *mut PyObject) -> *mut PyObject;
}
#[cfg(all(Py_3_10, not(Py_LIMITED_API)))]
#[cfg_attr(docsrs, doc(cfg(Py_3_10)))]
#[inline]
pub unsafe fn Py_NewRef(obj: *mut PyObject) -> *mut PyObject {
Py_INCREF(obj);
obj
}
#[cfg(all(Py_3_10, not(Py_LIMITED_API)))]
#[cfg_attr(docsrs, doc(cfg(Py_3_10)))]
#[inline]
pub unsafe fn Py_XNewRef(obj: *mut PyObject) -> *mut PyObject {
Py_XINCREF(obj);
obj
}