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)] 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, Py_3_11))))] #[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(Py_3_8)]
107 #[cfg_attr(
108 all(not(any(PyPy, GraalPy)), not(Py_3_9)),
109 link_name = "_PyObject_VectorcallDict"
110 )]
111 #[cfg_attr(all(PyPy, not(Py_3_9)), link_name = "_PyPyObject_VectorcallDict")]
112 #[cfg_attr(all(PyPy, Py_3_9), link_name = "PyPyObject_VectorcallDict")]
113 pub fn PyObject_VectorcallDict(
114 callable: *mut PyObject,
115 args: *const *mut PyObject,
116 nargsf: size_t,
117 kwdict: *mut PyObject,
118 ) -> *mut PyObject;
119
120 #[cfg(Py_3_8)]
121 #[cfg_attr(not(any(Py_3_9, PyPy)), link_name = "_PyVectorcall_Call")]
122 #[cfg_attr(PyPy, link_name = "PyPyVectorcall_Call")]
123 pub fn PyVectorcall_Call(
124 callable: *mut PyObject,
125 tuple: *mut PyObject,
126 dict: *mut PyObject,
127 ) -> *mut PyObject;
128}
129
130#[cfg(all(Py_3_8, not(any(PyPy, GraalPy))))]
131#[inline(always)]
132pub unsafe fn _PyObject_FastCallTstate(
133 tstate: *mut PyThreadState,
134 func: *mut PyObject,
135 args: *const *mut PyObject,
136 nargs: Py_ssize_t,
137) -> *mut PyObject {
138 _PyObject_VectorcallTstate(tstate, func, args, nargs as size_t, std::ptr::null_mut())
139}
140
141#[cfg(all(Py_3_8, not(any(PyPy, GraalPy))))]
142#[inline(always)]
143pub unsafe fn _PyObject_FastCall(
144 func: *mut PyObject,
145 args: *const *mut PyObject,
146 nargs: Py_ssize_t,
147) -> *mut PyObject {
148 _PyObject_FastCallTstate(PyThreadState_GET(), func, args, nargs)
149}
150
151#[cfg(all(Py_3_8, not(any(PyPy, GraalPy))))]
152#[inline(always)]
153pub unsafe fn _PyObject_CallNoArg(func: *mut PyObject) -> *mut PyObject {
154 _PyObject_VectorcallTstate(
155 PyThreadState_GET(),
156 func,
157 std::ptr::null_mut(),
158 0,
159 std::ptr::null_mut(),
160 )
161}
162
163extern "C" {
164 #[cfg(PyPy)]
165 #[link_name = "_PyPyObject_CallNoArg"]
166 pub fn _PyObject_CallNoArg(func: *mut PyObject) -> *mut PyObject;
167}
168
169#[cfg(all(Py_3_8, not(any(PyPy, GraalPy))))]
170#[inline(always)]
171pub unsafe fn PyObject_CallOneArg(func: *mut PyObject, arg: *mut PyObject) -> *mut PyObject {
172 assert!(!arg.is_null());
173 let args_array = [std::ptr::null_mut(), arg];
174 let args = args_array.as_ptr().offset(1); let tstate = PyThreadState_GET();
176 let nargsf = 1 | PY_VECTORCALL_ARGUMENTS_OFFSET;
177 _PyObject_VectorcallTstate(tstate, func, args, nargsf, std::ptr::null_mut())
178}
179
180#[cfg(all(Py_3_9, not(any(PyPy, GraalPy))))]
181#[inline(always)]
182pub unsafe fn PyObject_CallMethodNoArgs(
183 self_: *mut PyObject,
184 name: *mut PyObject,
185) -> *mut PyObject {
186 crate::PyObject_VectorcallMethod(
187 name,
188 &self_,
189 1 | PY_VECTORCALL_ARGUMENTS_OFFSET,
190 std::ptr::null_mut(),
191 )
192}
193
194#[cfg(all(Py_3_9, not(any(PyPy, GraalPy))))]
195#[inline(always)]
196pub unsafe fn PyObject_CallMethodOneArg(
197 self_: *mut PyObject,
198 name: *mut PyObject,
199 arg: *mut PyObject,
200) -> *mut PyObject {
201 let args = [self_, arg];
202 assert!(!arg.is_null());
203 crate::PyObject_VectorcallMethod(
204 name,
205 args.as_ptr(),
206 2 | PY_VECTORCALL_ARGUMENTS_OFFSET,
207 std::ptr::null_mut(),
208 )
209}
210
211extern "C" {
218 #[cfg_attr(PyPy, link_name = "PyPyObject_LengthHint")]
219 pub fn PyObject_LengthHint(o: *mut PyObject, arg1: Py_ssize_t) -> Py_ssize_t;
220
221 #[cfg(not(Py_3_11))] #[cfg(all(Py_3_9, not(any(PyPy, GraalPy))))]
223 pub fn PyObject_CheckBuffer(obj: *mut PyObject) -> c_int;
224}
225
226#[cfg(not(any(Py_3_9, PyPy)))]
227#[inline]
228pub unsafe fn PyObject_CheckBuffer(o: *mut PyObject) -> c_int {
229 let tp_as_buffer = (*crate::Py_TYPE(o)).tp_as_buffer;
230 (!tp_as_buffer.is_null() && (*tp_as_buffer).bf_getbuffer.is_some()) as c_int
231}
232
233#[cfg(not(Py_3_11))] extern "C" {
235 #[cfg_attr(PyPy, link_name = "PyPyObject_GetBuffer")]
236 pub fn PyObject_GetBuffer(obj: *mut PyObject, view: *mut Py_buffer, flags: c_int) -> c_int;
237 #[cfg_attr(PyPy, link_name = "PyPyBuffer_GetPointer")]
238 pub fn PyBuffer_GetPointer(
239 view: *mut Py_buffer,
240 indices: *mut Py_ssize_t,
241 ) -> *mut std::os::raw::c_void;
242 #[cfg_attr(PyPy, link_name = "PyPyBuffer_SizeFromFormat")]
243 pub fn PyBuffer_SizeFromFormat(format: *const c_char) -> Py_ssize_t;
244 #[cfg_attr(PyPy, link_name = "PyPyBuffer_ToContiguous")]
245 pub fn PyBuffer_ToContiguous(
246 buf: *mut std::os::raw::c_void,
247 view: *mut Py_buffer,
248 len: Py_ssize_t,
249 order: c_char,
250 ) -> c_int;
251 #[cfg_attr(PyPy, link_name = "PyPyBuffer_FromContiguous")]
252 pub fn PyBuffer_FromContiguous(
253 view: *mut Py_buffer,
254 buf: *mut std::os::raw::c_void,
255 len: Py_ssize_t,
256 order: c_char,
257 ) -> c_int;
258 pub fn PyObject_CopyData(dest: *mut PyObject, src: *mut PyObject) -> c_int;
259 #[cfg_attr(PyPy, link_name = "PyPyBuffer_IsContiguous")]
260 pub fn PyBuffer_IsContiguous(view: *const Py_buffer, fort: c_char) -> c_int;
261 pub fn PyBuffer_FillContiguousStrides(
262 ndims: c_int,
263 shape: *mut Py_ssize_t,
264 strides: *mut Py_ssize_t,
265 itemsize: c_int,
266 fort: c_char,
267 );
268 #[cfg_attr(PyPy, link_name = "PyPyBuffer_FillInfo")]
269 pub fn PyBuffer_FillInfo(
270 view: *mut Py_buffer,
271 o: *mut PyObject,
272 buf: *mut std::os::raw::c_void,
273 len: Py_ssize_t,
274 readonly: c_int,
275 flags: c_int,
276 ) -> c_int;
277 #[cfg_attr(PyPy, link_name = "PyPyBuffer_Release")]
278 pub fn PyBuffer_Release(view: *mut Py_buffer);
279}
280
281pub const PY_ITERSEARCH_COUNT: c_int = 1;
290pub const PY_ITERSEARCH_INDEX: c_int = 2;
291pub const PY_ITERSEARCH_CONTAINS: c_int = 3;
292
293extern "C" {
294 #[cfg(not(any(PyPy, GraalPy)))]
295 pub fn _PySequence_IterSearch(
296 seq: *mut PyObject,
297 obj: *mut PyObject,
298 operation: c_int,
299 ) -> Py_ssize_t;
300}
301
302