1#[cfg(Py_3_15)]
2use crate::Py_ssize_t;
3#[cfg(Py_3_15)]
4use core::ffi::{c_int, c_void};
5
6#[cfg(Py_3_15)]
7pub type _Py_funcptr_t = unsafe extern "C" fn();
8
9#[derive(Copy, Clone)]
10#[repr(C)]
11#[cfg(Py_3_15)]
12pub union _anon_union_32b {
13 pub sl_reserved: u32,
14}
15
16#[derive(Copy, Clone)]
17#[repr(C)]
18#[cfg(Py_3_15)]
19pub union _anon_union_64b {
20 pub sl_ptr: *mut c_void,
21 pub sl_func: Option<_Py_funcptr_t>,
22 pub sl_size: Py_ssize_t,
23 pub sl_int64: i64,
24 pub sl_uint64: u64,
25}
26
27#[derive(Copy, Clone)]
28#[repr(C)]
29#[cfg(Py_3_15)]
30pub struct PySlot {
31 pub sl_id: u16,
32 pub sl_flags: u16,
33 pub anon1: _anon_union_32b,
34 pub anon2: _anon_union_64b,
35}
36
37#[cfg(Py_3_15)]
38pub const PySlot_OPTIONAL: u16 = 0x01;
39#[cfg(Py_3_15)]
40pub const PySlot_STATIC: u16 = 0x02;
41#[cfg(Py_3_15)]
42pub const PySlot_INTPTR: u16 = 0x04;
43#[cfg(Py_3_15)]
44pub const Py_slot_invalid: u16 = 0xffff;
45
46#[cfg(Py_3_15)]
53const fn safe_cast_c_int_to_u16(val: c_int) -> u16 {
54 if val >= 0 && val <= u16::MAX as c_int {
55 val as u16
56 } else {
57 panic!("Slot ID out of range for u16");
58 }
59}
60
61#[cfg(Py_3_15)]
62pub const fn PySlot_DATA(NAME: c_int, VALUE: *mut c_void) -> PySlot {
63 PySlot {
64 sl_id: safe_cast_c_int_to_u16(NAME),
65 sl_flags: PySlot_INTPTR,
66 anon1: _anon_union_32b { sl_reserved: 0 },
67 anon2: _anon_union_64b { sl_ptr: VALUE },
68 }
69}
70
71#[expect(clippy::incompatible_msrv, reason = "guarded by cfg(const_is_null)")]
72#[cfg(Py_3_15)]
73pub const unsafe fn PySlot_FUNC(NAME: c_int, VALUE: *mut c_void) -> PySlot {
74 #[cfg(const_is_null)]
75 assert!(!VALUE.is_null(), "value may not be null");
76 PySlot {
77 sl_id: safe_cast_c_int_to_u16(NAME),
78 sl_flags: 0,
79 anon1: _anon_union_32b { sl_reserved: 0 },
80 anon2: _anon_union_64b {
81 sl_func: Some(unsafe { core::mem::transmute::<*mut c_void, _Py_funcptr_t>(VALUE) }),
83 },
84 }
85}
86
87#[cfg(Py_3_15)]
88pub const fn PySlot_SIZE(NAME: c_int, VALUE: Py_ssize_t) -> PySlot {
89 PySlot {
90 sl_id: safe_cast_c_int_to_u16(NAME),
91 sl_flags: 0,
92 anon1: _anon_union_32b { sl_reserved: 0 },
93 anon2: _anon_union_64b { sl_size: VALUE },
94 }
95}
96
97#[cfg(Py_3_15)]
98pub const fn PySlot_INT64(NAME: c_int, VALUE: i64) -> PySlot {
99 PySlot {
100 sl_id: safe_cast_c_int_to_u16(NAME),
101 sl_flags: 0,
102 anon1: _anon_union_32b { sl_reserved: 0 },
103 anon2: _anon_union_64b { sl_int64: VALUE },
104 }
105}
106
107#[cfg(Py_3_15)]
108pub const fn PySlot_UINT64(NAME: c_int, VALUE: u64) -> PySlot {
109 PySlot {
110 sl_id: safe_cast_c_int_to_u16(NAME),
111 sl_flags: 0,
112 anon1: _anon_union_32b { sl_reserved: 0 },
113 anon2: _anon_union_64b { sl_uint64: VALUE },
114 }
115}
116
117#[cfg(Py_3_15)]
118pub const fn PySlot_STATIC_DATA(NAME: c_int, VALUE: *mut c_void) -> PySlot {
119 PySlot {
120 sl_id: safe_cast_c_int_to_u16(NAME),
121 sl_flags: PySlot_STATIC,
122 anon1: _anon_union_32b { sl_reserved: 0 },
123 anon2: _anon_union_64b { sl_ptr: VALUE },
124 }
125}
126
127#[cfg(Py_3_15)]
128pub const fn PySlot_PTR(NAME: c_int, VALUE: *mut c_void) -> PySlot {
129 PySlot {
130 sl_id: safe_cast_c_int_to_u16(NAME),
131 sl_flags: PySlot_INTPTR,
132 anon1: _anon_union_32b { sl_reserved: 0 },
133 anon2: _anon_union_64b { sl_ptr: VALUE },
134 }
135}
136
137#[cfg(Py_3_15)]
138pub const fn PySlot_PTR_STATIC(NAME: c_int, VALUE: *mut c_void) -> PySlot {
139 PySlot {
140 sl_id: safe_cast_c_int_to_u16(NAME),
141 sl_flags: PySlot_INTPTR | PySlot_STATIC,
142 anon1: _anon_union_32b { sl_reserved: 0 },
143 anon2: _anon_union_64b { sl_ptr: VALUE },
144 }
145}
146
147#[cfg(Py_3_15)]
148pub const fn PySlot_END() -> PySlot {
149 unsafe { core::mem::zeroed() }
151}