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