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) }),
82 },
83 }
84}
85
86#[cfg(Py_3_15)]
87pub const fn PySlot_SIZE(NAME: c_int, VALUE: Py_ssize_t) -> PySlot {
88 PySlot {
89 sl_id: safe_cast_c_int_to_u16(NAME),
90 sl_flags: 0,
91 anon1: _anon_union_32b { sl_reserved: 0 },
92 anon2: _anon_union_64b { sl_size: VALUE },
93 }
94}
95
96#[cfg(Py_3_15)]
97pub const fn PySlot_INT64(NAME: c_int, VALUE: i64) -> PySlot {
98 PySlot {
99 sl_id: safe_cast_c_int_to_u16(NAME),
100 sl_flags: 0,
101 anon1: _anon_union_32b { sl_reserved: 0 },
102 anon2: _anon_union_64b { sl_int64: VALUE },
103 }
104}
105
106#[cfg(Py_3_15)]
107pub const fn PySlot_UINT64(NAME: c_int, VALUE: u64) -> PySlot {
108 PySlot {
109 sl_id: safe_cast_c_int_to_u16(NAME),
110 sl_flags: 0,
111 anon1: _anon_union_32b { sl_reserved: 0 },
112 anon2: _anon_union_64b { sl_uint64: VALUE },
113 }
114}
115
116#[cfg(Py_3_15)]
117pub const fn PySlot_STATIC_DATA(NAME: c_int, VALUE: *mut c_void) -> PySlot {
118 PySlot {
119 sl_id: safe_cast_c_int_to_u16(NAME),
120 sl_flags: PySlot_STATIC,
121 anon1: _anon_union_32b { sl_reserved: 0 },
122 anon2: _anon_union_64b { sl_ptr: VALUE },
123 }
124}
125
126#[cfg(Py_3_15)]
127pub const fn PySlot_PTR(NAME: c_int, VALUE: *mut c_void) -> PySlot {
128 PySlot {
129 sl_id: safe_cast_c_int_to_u16(NAME),
130 sl_flags: PySlot_INTPTR,
131 anon1: _anon_union_32b { sl_reserved: 0 },
132 anon2: _anon_union_64b { sl_ptr: VALUE },
133 }
134}
135
136#[cfg(Py_3_15)]
137pub const fn PySlot_PTR_STATIC(NAME: c_int, VALUE: *mut c_void) -> PySlot {
138 PySlot {
139 sl_id: safe_cast_c_int_to_u16(NAME),
140 sl_flags: PySlot_INTPTR | PySlot_STATIC,
141 anon1: _anon_union_32b { sl_reserved: 0 },
142 anon2: _anon_union_64b { sl_ptr: VALUE },
143 }
144}
145
146#[cfg(Py_3_15)]
147pub const fn PySlot_END() -> PySlot {
148 unsafe { core::mem::zeroed() }
149}