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
141
142
143
144
145
146
147
148
149
150
use crate::object::*;
#[cfg(not(any(Py_LIMITED_API, PyPy)))]
use crate::pyport::Py_hash_t;
use crate::pyport::Py_ssize_t;
use std::os::raw::c_int;
use std::ptr::addr_of_mut;

pub const PySet_MINSIZE: usize = 8;

#[cfg(not(any(Py_LIMITED_API, PyPy)))]
#[repr(C)]
#[derive(Debug)]
pub struct setentry {
    pub key: *mut PyObject,
    pub hash: Py_hash_t,
}

#[cfg(not(any(Py_LIMITED_API, PyPy)))]
#[repr(C)]
#[derive(Debug)]
pub struct PySetObject {
    pub ob_base: PyObject,
    pub fill: Py_ssize_t,
    pub used: Py_ssize_t,
    pub mask: Py_ssize_t,
    pub table: *mut setentry,
    pub hash: Py_hash_t,
    pub finger: Py_ssize_t,
    pub smalltable: [setentry; PySet_MINSIZE],
    pub weakreflist: *mut PyObject,
}

// skipped
#[inline]
#[cfg(all(not(PyPy), not(Py_LIMITED_API)))]
pub unsafe fn PySet_GET_SIZE(so: *mut PyObject) -> Py_ssize_t {
    debug_assert_eq!(PyAnySet_Check(so), 1);
    let so = so.cast::<PySetObject>();
    (*so).used
}

#[cfg(not(Py_LIMITED_API))]
#[cfg_attr(windows, link(name = "pythonXY"))]
extern "C" {
    pub static mut _PySet_Dummy: *mut PyObject;
}

extern "C" {
    #[cfg(not(Py_LIMITED_API))]
    #[cfg_attr(PyPy, link_name = "_PyPySet_NextEntry")]
    pub fn _PySet_NextEntry(
        set: *mut PyObject,
        pos: *mut Py_ssize_t,
        key: *mut *mut PyObject,
        hash: *mut super::Py_hash_t,
    ) -> c_int;

    // skipped non-limited _PySet_Update
}

#[cfg_attr(windows, link(name = "pythonXY"))]
extern "C" {
    #[cfg_attr(PyPy, link_name = "PyPySet_Type")]
    pub static mut PySet_Type: PyTypeObject;
    #[cfg_attr(PyPy, link_name = "PyPyFrozenSet_Type")]
    pub static mut PyFrozenSet_Type: PyTypeObject;
    pub static mut PySetIter_Type: PyTypeObject;
}

extern "C" {
    #[cfg_attr(PyPy, link_name = "PyPySet_New")]
    pub fn PySet_New(arg1: *mut PyObject) -> *mut PyObject;
    #[cfg_attr(PyPy, link_name = "PyPyFrozenSet_New")]
    pub fn PyFrozenSet_New(arg1: *mut PyObject) -> *mut PyObject;

    #[cfg_attr(PyPy, link_name = "PyPySet_Add")]
    pub fn PySet_Add(set: *mut PyObject, key: *mut PyObject) -> c_int;
    #[cfg_attr(PyPy, link_name = "PyPySet_Clear")]
    pub fn PySet_Clear(set: *mut PyObject) -> c_int;
    #[cfg_attr(PyPy, link_name = "PyPySet_Contains")]
    pub fn PySet_Contains(anyset: *mut PyObject, key: *mut PyObject) -> c_int;
    #[cfg_attr(PyPy, link_name = "PyPySet_Discard")]
    pub fn PySet_Discard(set: *mut PyObject, key: *mut PyObject) -> c_int;
    #[cfg_attr(PyPy, link_name = "PyPySet_Pop")]
    pub fn PySet_Pop(set: *mut PyObject) -> *mut PyObject;
    #[cfg_attr(PyPy, link_name = "PyPySet_Size")]
    pub fn PySet_Size(anyset: *mut PyObject) -> Py_ssize_t;

    #[cfg(PyPy)]
    #[link_name = "PyPyFrozenSet_CheckExact"]
    pub fn PyFrozenSet_CheckExact(ob: *mut PyObject) -> c_int;
}

#[inline]
#[cfg(not(PyPy))]
pub unsafe fn PyFrozenSet_CheckExact(ob: *mut PyObject) -> c_int {
    (Py_TYPE(ob) == addr_of_mut!(PyFrozenSet_Type)) as c_int
}

extern "C" {
    #[cfg(PyPy)]
    #[link_name = "PyPyFrozenSet_Check"]
    pub fn PyFrozenSet_Check(ob: *mut PyObject) -> c_int;
}

#[inline]
#[cfg(not(PyPy))]
pub unsafe fn PyFrozenSet_Check(ob: *mut PyObject) -> c_int {
    (Py_TYPE(ob) == addr_of_mut!(PyFrozenSet_Type)
        || PyType_IsSubtype(Py_TYPE(ob), addr_of_mut!(PyFrozenSet_Type)) != 0) as c_int
}

extern "C" {
    #[cfg(PyPy)]
    #[link_name = "PyPyAnySet_CheckExact"]
    pub fn PyAnySet_CheckExact(ob: *mut PyObject) -> c_int;
}

#[inline]
#[cfg(not(PyPy))]
pub unsafe fn PyAnySet_CheckExact(ob: *mut PyObject) -> c_int {
    (Py_TYPE(ob) == addr_of_mut!(PySet_Type) || Py_TYPE(ob) == addr_of_mut!(PyFrozenSet_Type))
        as c_int
}

#[inline]
pub unsafe fn PyAnySet_Check(ob: *mut PyObject) -> c_int {
    (PyAnySet_CheckExact(ob) != 0
        || PyType_IsSubtype(Py_TYPE(ob), addr_of_mut!(PySet_Type)) != 0
        || PyType_IsSubtype(Py_TYPE(ob), addr_of_mut!(PyFrozenSet_Type)) != 0) as c_int
}

#[inline]
#[cfg(Py_3_10)]
pub unsafe fn PySet_CheckExact(op: *mut PyObject) -> c_int {
    crate::Py_IS_TYPE(op, addr_of_mut!(PySet_Type))
}

extern "C" {
    #[cfg(PyPy)]
    #[link_name = "PyPySet_Check"]
    pub fn PySet_Check(ob: *mut PyObject) -> c_int;
}

#[inline]
#[cfg(not(PyPy))]
pub unsafe fn PySet_Check(ob: *mut PyObject) -> c_int {
    (Py_TYPE(ob) == addr_of_mut!(PySet_Type)
        || PyType_IsSubtype(Py_TYPE(ob), addr_of_mut!(PySet_Type)) != 0) as c_int
}