1use crate::{PyObject, Py_ssize_t};
2#[cfg(any(not(PyPy), not(Py_3_11)))]
3use std::ffi::c_char;
4use std::ffi::c_int;
5
6#[cfg(not(Py_3_11))]
7use crate::Py_buffer;
8
9#[cfg(not(PyPy))]
10use crate::{
11 vectorcallfunc, PyCallable_Check, PyThreadState, PyThreadState_GET, PyTuple_Check,
12 PyType_HasFeature, Py_TPFLAGS_HAVE_VECTORCALL,
13};
14use libc::size_t;
15
16extern_libpython! {
17 #[cfg(not(any(PyPy, GraalPy)))]
18 pub fn _PyStack_AsDict(values: *const *mut PyObject, kwnames: *mut PyObject) -> *mut PyObject;
19}
20
21#[cfg(not(any(PyPy, GraalPy)))]
22const _PY_FASTCALL_SMALL_STACK: size_t = 5;
23
24extern_libpython! {
25 #[cfg(not(PyPy))]
26 pub fn _Py_CheckFunctionResult(
27 tstate: *mut PyThreadState,
28 callable: *mut PyObject,
29 result: *mut PyObject,
30 where_: *const c_char,
31 ) -> *mut PyObject;
32
33 #[cfg(not(PyPy))]
34 pub fn _PyObject_MakeTpCall(
35 tstate: *mut PyThreadState,
36 callable: *mut PyObject,
37 args: *const *mut PyObject,
38 nargs: Py_ssize_t,
39 keywords: *mut PyObject,
40 ) -> *mut PyObject;
41}
42
43const PY_VECTORCALL_ARGUMENTS_OFFSET: size_t =
44 1 << (8 * std::mem::size_of::<size_t>() as size_t - 1);
45
46#[inline(always)]
47pub unsafe fn PyVectorcall_NARGS(n: size_t) -> Py_ssize_t {
48 let n = n & !PY_VECTORCALL_ARGUMENTS_OFFSET;
49 n.try_into().expect("cannot fail due to mask")
50}
51
52#[cfg(not(PyPy))]
53#[inline(always)]
54pub unsafe fn PyVectorcall_Function(callable: *mut PyObject) -> Option<vectorcallfunc> {
55 assert!(!callable.is_null());
56 let tp = crate::Py_TYPE(callable);
57 if PyType_HasFeature(tp, Py_TPFLAGS_HAVE_VECTORCALL) == 0 {
58 return None;
59 }
60 assert!(PyCallable_Check(callable) > 0);
61 let offset = (*tp).tp_vectorcall_offset;
62 assert!(offset > 0);
63 let ptr = callable.cast::<c_char>().offset(offset).cast();
64 *ptr
65}
66
67#[cfg(not(PyPy))]
68#[inline(always)]
69pub unsafe fn _PyObject_VectorcallTstate(
70 tstate: *mut PyThreadState,
71 callable: *mut PyObject,
72 args: *const *mut PyObject,
73 nargsf: size_t,
74 kwnames: *mut PyObject,
75) -> *mut PyObject {
76 assert!(kwnames.is_null() || PyTuple_Check(kwnames) > 0);
77 assert!(!args.is_null() || PyVectorcall_NARGS(nargsf) == 0);
78
79 match PyVectorcall_Function(callable) {
80 None => {
81 let nargs = PyVectorcall_NARGS(nargsf);
82 _PyObject_MakeTpCall(tstate, callable, args, nargs, kwnames)
83 }
84 Some(func) => {
85 let res = func(callable, args, nargsf, kwnames);
86 _Py_CheckFunctionResult(tstate, callable, res, std::ptr::null_mut())
87 }
88 }
89}
90
91#[cfg(not(any(PyPy, GraalPy, Py_3_11)))] #[inline(always)]
93pub unsafe fn PyObject_Vectorcall(
94 callable: *mut PyObject,
95 args: *const *mut PyObject,
96 nargsf: size_t,
97 kwnames: *mut PyObject,
98) -> *mut PyObject {
99 _PyObject_VectorcallTstate(PyThreadState_GET(), callable, args, nargsf, kwnames)
100}
101
102extern_libpython! {
103 #[cfg_attr(
104 all(not(any(PyPy, GraalPy)), not(Py_3_9)),
105 link_name = "_PyObject_VectorcallDict"
106 )]
107 #[cfg_attr(all(PyPy, not(Py_3_9)), link_name = "_PyPyObject_VectorcallDict")]
108 #[cfg_attr(all(PyPy, Py_3_9), link_name = "PyPyObject_VectorcallDict")]
109 pub fn PyObject_VectorcallDict(
110 callable: *mut PyObject,
111 args: *const *mut PyObject,
112 nargsf: size_t,
113 kwdict: *mut PyObject,
114 ) -> *mut PyObject;
115
116 #[cfg_attr(not(any(Py_3_9, PyPy)), link_name = "_PyVectorcall_Call")]
117 #[cfg_attr(PyPy, link_name = "PyPyVectorcall_Call")]
118 pub fn PyVectorcall_Call(
119 callable: *mut PyObject,
120 tuple: *mut PyObject,
121 dict: *mut PyObject,
122 ) -> *mut PyObject;
123}
124
125#[cfg(not(any(PyPy, GraalPy)))]
126#[inline(always)]
127pub unsafe fn _PyObject_FastCallTstate(
128 tstate: *mut PyThreadState,
129 func: *mut PyObject,
130 args: *const *mut PyObject,
131 nargs: Py_ssize_t,
132) -> *mut PyObject {
133 _PyObject_VectorcallTstate(tstate, func, args, nargs as size_t, std::ptr::null_mut())
134}
135
136#[cfg(not(any(PyPy, GraalPy)))]
137#[inline(always)]
138pub unsafe fn _PyObject_FastCall(
139 func: *mut PyObject,
140 args: *const *mut PyObject,
141 nargs: Py_ssize_t,
142) -> *mut PyObject {
143 _PyObject_FastCallTstate(PyThreadState_GET(), func, args, nargs)
144}
145
146#[cfg(not(PyPy))]
147#[inline(always)]
148pub unsafe fn _PyObject_CallNoArg(func: *mut PyObject) -> *mut PyObject {
149 _PyObject_VectorcallTstate(
150 PyThreadState_GET(),
151 func,
152 std::ptr::null_mut(),
153 0,
154 std::ptr::null_mut(),
155 )
156}
157
158extern_libpython! {
159 #[cfg(PyPy)]
160 #[link_name = "_PyPyObject_CallNoArg"]
161 pub fn _PyObject_CallNoArg(func: *mut PyObject) -> *mut PyObject;
162}
163
164#[cfg(not(PyPy))]
165#[inline(always)]
166pub unsafe fn PyObject_CallOneArg(func: *mut PyObject, arg: *mut PyObject) -> *mut PyObject {
167 assert!(!arg.is_null());
168 let args_array = [std::ptr::null_mut(), arg];
169 let args = args_array.as_ptr().offset(1); let tstate = PyThreadState_GET();
171 let nargsf = 1 | PY_VECTORCALL_ARGUMENTS_OFFSET;
172 _PyObject_VectorcallTstate(tstate, func, args, nargsf, std::ptr::null_mut())
173}
174
175#[cfg(all(Py_3_9, not(PyPy)))]
176#[inline(always)]
177pub unsafe fn PyObject_CallMethodNoArgs(
178 self_: *mut PyObject,
179 name: *mut PyObject,
180) -> *mut PyObject {
181 crate::PyObject_VectorcallMethod(
182 name,
183 &self_,
184 1 | PY_VECTORCALL_ARGUMENTS_OFFSET,
185 std::ptr::null_mut(),
186 )
187}
188
189#[cfg(all(Py_3_9, not(PyPy)))]
190#[inline(always)]
191pub unsafe fn PyObject_CallMethodOneArg(
192 self_: *mut PyObject,
193 name: *mut PyObject,
194 arg: *mut PyObject,
195) -> *mut PyObject {
196 let args = [self_, arg];
197 assert!(!arg.is_null());
198 crate::PyObject_VectorcallMethod(
199 name,
200 args.as_ptr(),
201 2 | PY_VECTORCALL_ARGUMENTS_OFFSET,
202 std::ptr::null_mut(),
203 )
204}
205
206extern_libpython! {
213 #[cfg_attr(PyPy, link_name = "PyPyObject_LengthHint")]
214 pub fn PyObject_LengthHint(o: *mut PyObject, arg1: Py_ssize_t) -> Py_ssize_t;
215
216 #[cfg(not(Py_3_11))] #[cfg(all(Py_3_9, not(PyPy)))]
218 pub fn PyObject_CheckBuffer(obj: *mut PyObject) -> c_int;
219}
220
221#[cfg(not(any(Py_3_9, PyPy)))]
222#[inline]
223pub unsafe fn PyObject_CheckBuffer(o: *mut PyObject) -> c_int {
224 let tp_as_buffer = (*crate::Py_TYPE(o)).tp_as_buffer;
225 (!tp_as_buffer.is_null() && (*tp_as_buffer).bf_getbuffer.is_some()) as c_int
226}
227
228#[cfg(not(Py_3_11))] extern_libpython! {
230 #[cfg_attr(PyPy, link_name = "PyPyObject_GetBuffer")]
231 pub fn PyObject_GetBuffer(obj: *mut PyObject, view: *mut Py_buffer, flags: c_int) -> c_int;
232 #[cfg_attr(PyPy, link_name = "PyPyBuffer_GetPointer")]
233 pub fn PyBuffer_GetPointer(
234 view: *mut Py_buffer,
235 indices: *mut Py_ssize_t,
236 ) -> *mut std::ffi::c_void;
237 #[cfg_attr(PyPy, link_name = "PyPyBuffer_SizeFromFormat")]
238 pub fn PyBuffer_SizeFromFormat(format: *const c_char) -> Py_ssize_t;
239 #[cfg_attr(PyPy, link_name = "PyPyBuffer_ToContiguous")]
240 pub fn PyBuffer_ToContiguous(
241 buf: *mut std::ffi::c_void,
242 view: *mut Py_buffer,
243 len: Py_ssize_t,
244 order: c_char,
245 ) -> c_int;
246 #[cfg_attr(PyPy, link_name = "PyPyBuffer_FromContiguous")]
247 pub fn PyBuffer_FromContiguous(
248 view: *mut Py_buffer,
249 buf: *mut std::ffi::c_void,
250 len: Py_ssize_t,
251 order: c_char,
252 ) -> c_int;
253 pub fn PyObject_CopyData(dest: *mut PyObject, src: *mut PyObject) -> c_int;
254 #[cfg_attr(PyPy, link_name = "PyPyBuffer_IsContiguous")]
255 pub fn PyBuffer_IsContiguous(view: *const Py_buffer, fort: c_char) -> c_int;
256 pub fn PyBuffer_FillContiguousStrides(
257 ndims: c_int,
258 shape: *mut Py_ssize_t,
259 strides: *mut Py_ssize_t,
260 itemsize: c_int,
261 fort: c_char,
262 );
263 #[cfg_attr(PyPy, link_name = "PyPyBuffer_FillInfo")]
264 pub fn PyBuffer_FillInfo(
265 view: *mut Py_buffer,
266 o: *mut PyObject,
267 buf: *mut std::ffi::c_void,
268 len: Py_ssize_t,
269 readonly: c_int,
270 flags: c_int,
271 ) -> c_int;
272 #[cfg_attr(PyPy, link_name = "PyPyBuffer_Release")]
273 pub fn PyBuffer_Release(view: *mut Py_buffer);
274}
275
276pub const PY_ITERSEARCH_COUNT: c_int = 1;
279pub const PY_ITERSEARCH_INDEX: c_int = 2;
280pub const PY_ITERSEARCH_CONTAINS: c_int = 3;
281
282extern_libpython! {
283 #[cfg(not(any(PyPy, GraalPy)))]
284 pub fn _PySequence_IterSearch(
285 seq: *mut PyObject,
286 obj: *mut PyObject,
287 operation: c_int,
288 ) -> Py_ssize_t;
289}
290
291