Skip to main content

pyo3_ffi/cpython/
unicodeobject.rs

1#[cfg(any(Py_3_11, not(PyPy)))]
2use crate::Py_hash_t;
3use crate::{PyObject, Py_UCS1, Py_UCS2, Py_UCS4, Py_ssize_t};
4use core::ffi::{c_char, c_int, c_uint, c_void};
5use libc::wchar_t;
6
7// skipped PY_UNICODE_TYPE
8
9#[cfg(not(Py_LIMITED_API))]
10#[cfg_attr(
11    Py_3_13,
12    deprecated(note = "Deprecated since Python 3.13. Use `libc::wchar_t` instead.")
13)]
14pub type Py_UNICODE = wchar_t;
15
16// skipped Py_UNICODE_IS_SURROGATE
17// skipped Py_UNICODE_IS_HIGH_SURROGATE
18// skipped Py_UNICODE_IS_LOW_SURROGATE
19// skipped Py_UNICODE_JOIN_SURROGATES
20// skipped Py_UNICODE_HIGH_SURROGATE
21// skipped Py_UNICODE_LOW_SURROGATE
22
23// generated by bindgen v0.63.0 (with small adaptations)
24#[cfg(not(Py_3_14))]
25#[repr(C)]
26struct BitfieldUnit<Storage> {
27    storage: Storage,
28}
29
30#[cfg(not(Py_3_14))]
31impl<Storage> BitfieldUnit<Storage> {
32    #[inline]
33    pub const fn new(storage: Storage) -> Self {
34        Self { storage }
35    }
36}
37
38#[cfg(not(any(GraalPy, Py_3_14)))]
39impl<Storage> BitfieldUnit<Storage>
40where
41    Storage: AsRef<[u8]> + AsMut<[u8]>,
42{
43    #[inline]
44    fn get_bit(&self, index: usize) -> bool {
45        debug_assert!(index / 8 < self.storage.as_ref().len());
46        let byte_index = index / 8;
47        let byte = self.storage.as_ref()[byte_index];
48        let bit_index = if cfg!(target_endian = "big") {
49            7 - (index % 8)
50        } else {
51            index % 8
52        };
53        let mask = 1 << bit_index;
54        byte & mask == mask
55    }
56
57    #[inline]
58    fn set_bit(&mut self, index: usize, val: bool) {
59        debug_assert!(index / 8 < self.storage.as_ref().len());
60        let byte_index = index / 8;
61        let byte = &mut self.storage.as_mut()[byte_index];
62        let bit_index = if cfg!(target_endian = "big") {
63            7 - (index % 8)
64        } else {
65            index % 8
66        };
67        let mask = 1 << bit_index;
68        if val {
69            *byte |= mask;
70        } else {
71            *byte &= !mask;
72        }
73    }
74
75    #[inline]
76    fn get(&self, bit_offset: usize, bit_width: u8) -> u64 {
77        debug_assert!(bit_width <= 64);
78        debug_assert!(bit_offset / 8 < self.storage.as_ref().len());
79        debug_assert!((bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len());
80        let mut val = 0;
81        for i in 0..(bit_width as usize) {
82            if self.get_bit(i + bit_offset) {
83                let index = if cfg!(target_endian = "big") {
84                    bit_width as usize - 1 - i
85                } else {
86                    i
87                };
88                val |= 1 << index;
89            }
90        }
91        val
92    }
93
94    #[inline]
95    fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) {
96        debug_assert!(bit_width <= 64);
97        debug_assert!(bit_offset / 8 < self.storage.as_ref().len());
98        debug_assert!((bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len());
99        for i in 0..(bit_width as usize) {
100            let mask = 1 << i;
101            let val_bit_is_set = val & mask == mask;
102            let index = if cfg!(target_endian = "big") {
103                bit_width as usize - 1 - i
104            } else {
105                i
106            };
107            self.set_bit(index + bit_offset, val_bit_is_set);
108        }
109    }
110}
111
112#[cfg(not(any(GraalPy, Py_3_14)))]
113const STATE_INTERNED_INDEX: usize = 0;
114#[cfg(not(any(GraalPy, Py_3_14)))]
115const STATE_INTERNED_WIDTH: u8 = 2;
116
117#[cfg(not(any(GraalPy, Py_3_14)))]
118const STATE_KIND_INDEX: usize = STATE_INTERNED_WIDTH as usize;
119#[cfg(not(any(GraalPy, Py_3_14)))]
120const STATE_KIND_WIDTH: u8 = 3;
121
122#[cfg(not(any(GraalPy, Py_3_14)))]
123const STATE_COMPACT_INDEX: usize = (STATE_INTERNED_WIDTH + STATE_KIND_WIDTH) as usize;
124#[cfg(not(any(GraalPy, Py_3_14)))]
125const STATE_COMPACT_WIDTH: u8 = 1;
126
127#[cfg(not(any(GraalPy, Py_3_14)))]
128const STATE_ASCII_INDEX: usize =
129    (STATE_INTERNED_WIDTH + STATE_KIND_WIDTH + STATE_COMPACT_WIDTH) as usize;
130#[cfg(not(any(GraalPy, Py_3_14)))]
131const STATE_ASCII_WIDTH: u8 = 1;
132
133#[cfg(all(not(any(GraalPy, Py_3_14)), Py_3_12))]
134const STATE_STATICALLY_ALLOCATED_INDEX: usize =
135    (STATE_INTERNED_WIDTH + STATE_KIND_WIDTH + STATE_COMPACT_WIDTH + STATE_ASCII_WIDTH) as usize;
136#[cfg(all(not(any(GraalPy, Py_3_14)), Py_3_12))]
137const STATE_STATICALLY_ALLOCATED_WIDTH: u8 = 1;
138
139#[cfg(not(any(Py_3_12, GraalPy)))]
140const STATE_READY_INDEX: usize =
141    (STATE_INTERNED_WIDTH + STATE_KIND_WIDTH + STATE_COMPACT_WIDTH + STATE_ASCII_WIDTH) as usize;
142#[cfg(not(any(Py_3_12, GraalPy)))]
143const STATE_READY_WIDTH: u8 = 1;
144
145// generated by bindgen v0.63.0 (with small adaptations)
146// The same code is generated for Python 3.8, 3.9, 3.10, and 3.11, but the "ready" field
147// has been removed from Python 3.12.
148
149/// Wrapper around the `PyASCIIObject.state` bitfield with getters and setters that work
150/// on most little- and big-endian architectures.
151///
152/// Memory layout of C bitfields is implementation defined, so these functions are still
153/// unsafe. Users must verify that they work as expected on the architectures they target.
154#[cfg(not(Py_3_14))]
155#[repr(C)]
156struct PyASCIIObjectState {
157    bitfield_align: [u8; 0],
158    bitfield: BitfieldUnit<[u8; 4usize]>,
159}
160
161// c_uint and u32 are not necessarily the same type on all targets / architectures
162#[cfg(not(any(GraalPy, Py_3_14)))]
163#[allow(clippy::useless_transmute)]
164impl PyASCIIObjectState {
165    #[inline]
166    unsafe fn interned(&self) -> c_uint {
167        core::mem::transmute(
168            self.bitfield
169                .get(STATE_INTERNED_INDEX, STATE_INTERNED_WIDTH) as u32,
170        )
171    }
172
173    #[inline]
174    unsafe fn set_interned(&mut self, val: c_uint) {
175        let val: u32 = core::mem::transmute(val);
176        self.bitfield
177            .set(STATE_INTERNED_INDEX, STATE_INTERNED_WIDTH, val as u64)
178    }
179
180    #[inline]
181    unsafe fn kind(&self) -> c_uint {
182        core::mem::transmute(self.bitfield.get(STATE_KIND_INDEX, STATE_KIND_WIDTH) as u32)
183    }
184
185    #[inline]
186    unsafe fn set_kind(&mut self, val: c_uint) {
187        let val: u32 = core::mem::transmute(val);
188        self.bitfield
189            .set(STATE_KIND_INDEX, STATE_KIND_WIDTH, val as u64)
190    }
191
192    #[inline]
193    unsafe fn compact(&self) -> c_uint {
194        core::mem::transmute(self.bitfield.get(STATE_COMPACT_INDEX, STATE_COMPACT_WIDTH) as u32)
195    }
196
197    #[inline]
198    unsafe fn set_compact(&mut self, val: c_uint) {
199        let val: u32 = core::mem::transmute(val);
200        self.bitfield
201            .set(STATE_COMPACT_INDEX, STATE_COMPACT_WIDTH, val as u64)
202    }
203
204    #[inline]
205    unsafe fn ascii(&self) -> c_uint {
206        core::mem::transmute(self.bitfield.get(STATE_ASCII_INDEX, STATE_ASCII_WIDTH) as u32)
207    }
208
209    #[inline]
210    unsafe fn set_ascii(&mut self, val: c_uint) {
211        let val: u32 = core::mem::transmute(val);
212        self.bitfield
213            .set(STATE_ASCII_INDEX, STATE_ASCII_WIDTH, val as u64)
214    }
215
216    #[cfg(Py_3_12)]
217    #[inline]
218    unsafe fn statically_allocated(&self) -> c_uint {
219        core::mem::transmute(self.bitfield.get(
220            STATE_STATICALLY_ALLOCATED_INDEX,
221            STATE_STATICALLY_ALLOCATED_WIDTH,
222        ) as u32)
223    }
224
225    #[cfg(Py_3_12)]
226    #[inline]
227    unsafe fn set_statically_allocated(&mut self, val: c_uint) {
228        let val: u32 = core::mem::transmute(val);
229        self.bitfield.set(
230            STATE_STATICALLY_ALLOCATED_INDEX,
231            STATE_STATICALLY_ALLOCATED_WIDTH,
232            val as u64,
233        )
234    }
235
236    #[cfg(not(Py_3_12))]
237    #[inline]
238    unsafe fn ready(&self) -> c_uint {
239        core::mem::transmute(self.bitfield.get(STATE_READY_INDEX, STATE_READY_WIDTH) as u32)
240    }
241
242    #[cfg(not(Py_3_12))]
243    #[inline]
244    unsafe fn set_ready(&mut self, val: c_uint) {
245        let val: u32 = core::mem::transmute(val);
246        self.bitfield
247            .set(STATE_READY_INDEX, STATE_READY_WIDTH, val as u64)
248    }
249}
250
251#[cfg(not(Py_3_14))]
252impl From<u32> for PyASCIIObjectState {
253    #[inline]
254    fn from(value: u32) -> Self {
255        PyASCIIObjectState {
256            bitfield_align: [],
257            bitfield: BitfieldUnit::new(value.to_ne_bytes()),
258        }
259    }
260}
261
262#[cfg(not(Py_3_14))]
263impl From<PyASCIIObjectState> for u32 {
264    #[inline]
265    fn from(value: PyASCIIObjectState) -> Self {
266        u32::from_ne_bytes(value.bitfield.storage)
267    }
268}
269
270#[repr(C)]
271pub struct PyASCIIObject {
272    pub ob_base: PyObject,
273    pub length: Py_ssize_t,
274    #[cfg(any(Py_3_11, not(PyPy)))]
275    pub hash: Py_hash_t,
276    /// A bit field with various properties.
277    ///
278    /// Rust doesn't expose bitfields. So we have accessor functions for
279    /// retrieving values.
280    ///
281    /// Before 3.12:
282    /// unsigned int interned:2; // SSTATE_* constants.
283    /// unsigned int kind:3;     // PyUnicode_*_KIND constants.
284    /// unsigned int compact:1;
285    /// unsigned int ascii:1;
286    /// unsigned int ready:1;
287    /// unsigned int :24;
288    ///
289    /// 3.12, and 3.13
290    /// unsigned int interned:2; // SSTATE_* constants.
291    /// unsigned int kind:3;     // PyUnicode_*_KIND constants.
292    /// unsigned int compact:1;
293    /// unsigned int ascii:1;
294    /// unsigned int statically_allocated:1;
295    /// unsigned int :24;
296    /// on 3.14 and higher PyO3 doesn't access the internal state
297    pub state: u32,
298    #[cfg(not(Py_3_12))]
299    pub wstr: *mut wchar_t,
300}
301
302/// Interacting with the bitfield is not actually well-defined, so we mark these APIs unsafe.
303#[cfg(not(any(GraalPy, Py_3_14)))]
304impl PyASCIIObject {
305    #[cfg_attr(not(Py_3_12), allow(rustdoc::broken_intra_doc_links))] // SSTATE_INTERNED_IMMORTAL_STATIC requires 3.12
306    /// Get the `interned` field of the [`PyASCIIObject`] state bitfield.
307    ///
308    /// Returns one of: [`SSTATE_NOT_INTERNED`], [`SSTATE_INTERNED_MORTAL`],
309    /// [`SSTATE_INTERNED_IMMORTAL`], or [`SSTATE_INTERNED_IMMORTAL_STATIC`].
310    #[inline]
311    pub unsafe fn interned(&self) -> c_uint {
312        PyASCIIObjectState::from(self.state).interned()
313    }
314
315    #[cfg_attr(not(Py_3_12), allow(rustdoc::broken_intra_doc_links))] // SSTATE_INTERNED_IMMORTAL_STATIC requires 3.12
316    /// Set the `interned` field of the [`PyASCIIObject`] state bitfield.
317    ///
318    /// Calling this function with an argument that is not [`SSTATE_NOT_INTERNED`],
319    /// [`SSTATE_INTERNED_MORTAL`], [`SSTATE_INTERNED_IMMORTAL`], or
320    /// [`SSTATE_INTERNED_IMMORTAL_STATIC`] is invalid.
321    #[inline]
322    pub unsafe fn set_interned(&mut self, val: c_uint) {
323        let mut state = PyASCIIObjectState::from(self.state);
324        state.set_interned(val);
325        self.state = u32::from(state);
326    }
327
328    /// Get the `kind` field of the [`PyASCIIObject`] state bitfield.
329    ///
330    /// Returns one of:
331    #[cfg_attr(not(Py_3_12), doc = "[`PyUnicode_WCHAR_KIND`], ")]
332    /// [`PyUnicode_1BYTE_KIND`], [`PyUnicode_2BYTE_KIND`], or [`PyUnicode_4BYTE_KIND`].
333    #[inline]
334    pub unsafe fn kind(&self) -> c_uint {
335        PyASCIIObjectState::from(self.state).kind()
336    }
337
338    /// Set the `kind` field of the [`PyASCIIObject`] state bitfield.
339    ///
340    /// Calling this function with an argument that is not
341    #[cfg_attr(not(Py_3_12), doc = "[`PyUnicode_WCHAR_KIND`], ")]
342    /// [`PyUnicode_1BYTE_KIND`], [`PyUnicode_2BYTE_KIND`], or [`PyUnicode_4BYTE_KIND`] is invalid.
343    #[inline]
344    pub unsafe fn set_kind(&mut self, val: c_uint) {
345        let mut state = PyASCIIObjectState::from(self.state);
346        state.set_kind(val);
347        self.state = u32::from(state);
348    }
349
350    /// Get the `compact` field of the [`PyASCIIObject`] state bitfield.
351    ///
352    /// Returns either `0` or `1`.
353    #[inline]
354    pub unsafe fn compact(&self) -> c_uint {
355        PyASCIIObjectState::from(self.state).compact()
356    }
357
358    /// Set the `compact` flag of the [`PyASCIIObject`] state bitfield.
359    ///
360    /// Calling this function with an argument that is neither `0` nor `1` is invalid.
361    #[inline]
362    pub unsafe fn set_compact(&mut self, val: c_uint) {
363        let mut state = PyASCIIObjectState::from(self.state);
364        state.set_compact(val);
365        self.state = u32::from(state);
366    }
367
368    /// Get the `ascii` field of the [`PyASCIIObject`] state bitfield.
369    ///
370    /// Returns either `0` or `1`.
371    #[inline]
372    pub unsafe fn ascii(&self) -> c_uint {
373        PyASCIIObjectState::from(self.state).ascii()
374    }
375
376    /// Set the `ascii` flag of the [`PyASCIIObject`] state bitfield.
377    ///
378    /// Calling this function with an argument that is neither `0` nor `1` is invalid.
379    #[inline]
380    #[cfg(not(all(Py_3_14, Py_GIL_DISABLED)))]
381    pub unsafe fn set_ascii(&mut self, val: c_uint) {
382        let mut state = PyASCIIObjectState::from(self.state);
383        state.set_ascii(val);
384        self.state = u32::from(state);
385    }
386
387    /// Get the `ready` field of the [`PyASCIIObject`] state bitfield.
388    ///
389    /// Returns either `0` or `1`.
390    #[cfg(not(Py_3_12))]
391    #[inline]
392    pub unsafe fn ready(&self) -> c_uint {
393        PyASCIIObjectState::from(self.state).ready()
394    }
395
396    /// Set the `ready` flag of the [`PyASCIIObject`] state bitfield.
397    ///
398    /// Calling this function with an argument that is neither `0` nor `1` is invalid.
399    #[cfg(not(Py_3_12))]
400    #[inline]
401    pub unsafe fn set_ready(&mut self, val: c_uint) {
402        let mut state = PyASCIIObjectState::from(self.state);
403        state.set_ready(val);
404        self.state = u32::from(state);
405    }
406
407    /// Get the `statically_allocated` field of the [`PyASCIIObject`] state bitfield.
408    ///
409    /// Returns either `0` or `1`.
410    #[inline]
411    #[cfg(Py_3_12)]
412    pub unsafe fn statically_allocated(&self) -> c_uint {
413        PyASCIIObjectState::from(self.state).statically_allocated()
414    }
415
416    /// Set the `statically_allocated` flag of the [`PyASCIIObject`] state bitfield.
417    ///
418    /// Calling this function with an argument that is neither `0` nor `1` is invalid.
419    #[inline]
420    #[cfg(Py_3_12)]
421    pub unsafe fn set_statically_allocated(&mut self, val: c_uint) {
422        let mut state = PyASCIIObjectState::from(self.state);
423        state.set_statically_allocated(val);
424        self.state = u32::from(state);
425    }
426}
427
428#[repr(C)]
429pub struct PyCompactUnicodeObject {
430    pub _base: PyASCIIObject,
431    pub utf8_length: Py_ssize_t,
432    pub utf8: *mut c_char,
433    #[cfg(not(Py_3_12))]
434    pub wstr_length: Py_ssize_t,
435}
436
437#[repr(C)]
438pub union PyUnicodeObjectData {
439    pub any: *mut c_void,
440    pub latin1: *mut Py_UCS1,
441    pub ucs2: *mut Py_UCS2,
442    pub ucs4: *mut Py_UCS4,
443}
444
445#[repr(C)]
446pub struct PyUnicodeObject {
447    pub _base: PyCompactUnicodeObject,
448    pub data: PyUnicodeObjectData,
449}
450
451// skipped private _PyASCIIObject_CAST
452// skipped private _PyCompactUnicodeObject_CAST
453// skipped private _PyUnicodeObject_CAST
454
455pub const SSTATE_NOT_INTERNED: c_uint = 0;
456pub const SSTATE_INTERNED_MORTAL: c_uint = 1;
457pub const SSTATE_INTERNED_IMMORTAL: c_uint = 2;
458#[cfg(Py_3_12)]
459pub const SSTATE_INTERNED_IMMORTAL_STATIC: c_uint = 3;
460
461// skipped PyUnicode_CHECK_INTERNED
462
463#[cfg(any(Py_3_12, GraalPy))]
464#[cfg_attr(
465    Py_3_14,
466    deprecated(note = "Deprecated since Python 3.14. This API does nothing since Python 3.12.")
467)]
468#[inline]
469pub unsafe fn PyUnicode_IS_READY(_op: *mut PyObject) -> c_uint {
470    // kept in CPython for backwards compatibility
471    1
472}
473
474#[cfg(not(any(GraalPy, Py_3_12)))]
475#[inline]
476pub unsafe fn PyUnicode_IS_READY(op: *mut PyObject) -> c_uint {
477    (*(op as *mut PyASCIIObject)).ready()
478}
479
480// The following functions depend on the bitfield, which we don't support
481// from 3.14 onwards
482
483#[cfg(not(any(GraalPy, Py_3_14)))]
484#[inline]
485pub unsafe fn PyUnicode_IS_ASCII(op: *mut PyObject) -> c_uint {
486    debug_assert!(crate::PyUnicode_Check(op) != 0);
487    #[cfg(not(Py_3_12))]
488    debug_assert!(PyUnicode_IS_READY(op) != 0);
489
490    (*(op as *mut PyASCIIObject)).ascii()
491}
492
493#[cfg(not(any(GraalPy, Py_3_14)))]
494#[inline]
495pub unsafe fn PyUnicode_IS_COMPACT(op: *mut PyObject) -> c_uint {
496    (*(op as *mut PyASCIIObject)).compact()
497}
498
499#[cfg(not(any(GraalPy, Py_3_14)))]
500#[inline]
501pub unsafe fn PyUnicode_IS_COMPACT_ASCII(op: *mut PyObject) -> c_uint {
502    ((*(op as *mut PyASCIIObject)).ascii() != 0 && PyUnicode_IS_COMPACT(op) != 0).into()
503}
504
505#[cfg(not(Py_3_12))]
506#[deprecated(note = "Removed in Python 3.12")]
507pub const PyUnicode_WCHAR_KIND: c_uint = 0;
508
509pub const PyUnicode_1BYTE_KIND: c_uint = 1;
510pub const PyUnicode_2BYTE_KIND: c_uint = 2;
511pub const PyUnicode_4BYTE_KIND: c_uint = 4;
512
513#[cfg(all(not(GraalPy), Py_3_14))]
514extern_libpython! {
515    #[cfg_attr(PyPy, link_name = "PyPyUnicode_KIND")]
516    pub fn PyUnicode_KIND(op: *mut PyObject) -> c_uint;
517}
518
519#[cfg(all(not(GraalPy), not(Py_3_14)))]
520#[inline]
521pub unsafe fn PyUnicode_KIND(op: *mut PyObject) -> c_uint {
522    debug_assert!(crate::PyUnicode_Check(op) != 0);
523    #[cfg(not(Py_3_12))]
524    debug_assert!(PyUnicode_IS_READY(op) != 0);
525
526    (*(op as *mut PyASCIIObject)).kind()
527}
528
529#[cfg(not(any(GraalPy, Py_3_14)))]
530#[inline]
531unsafe fn _PyUnicode_COMPACT_DATA(op: *mut PyObject) -> *mut c_void {
532    if PyUnicode_IS_ASCII(op) != 0 {
533        (op as *mut PyASCIIObject).offset(1) as *mut c_void
534    } else {
535        (op as *mut PyCompactUnicodeObject).offset(1) as *mut c_void
536    }
537}
538
539#[cfg(not(any(GraalPy, PyPy)))]
540#[inline]
541unsafe fn _PyUnicode_NONCOMPACT_DATA(op: *mut PyObject) -> *mut c_void {
542    debug_assert!(!(*(op as *mut PyUnicodeObject)).data.any.is_null());
543
544    (*(op as *mut PyUnicodeObject)).data.any
545}
546
547#[cfg(not(any(GraalPy, PyPy, Py_3_14)))]
548#[inline]
549pub unsafe fn PyUnicode_DATA(op: *mut PyObject) -> *mut c_void {
550    debug_assert!(crate::PyUnicode_Check(op) != 0);
551
552    if PyUnicode_IS_COMPACT(op) != 0 {
553        _PyUnicode_COMPACT_DATA(op)
554    } else {
555        _PyUnicode_NONCOMPACT_DATA(op)
556    }
557}
558
559#[cfg(Py_3_14)]
560#[cfg(all(not(GraalPy), Py_3_14))]
561extern_libpython! {
562    #[cfg_attr(PyPy, link_name = "PyPyUnicode_DATA")]
563    pub fn PyUnicode_DATA(op: *mut PyObject) -> *mut c_void;
564}
565
566#[cfg(not(any(GraalPy, PyPy)))]
567#[inline]
568pub unsafe fn PyUnicode_1BYTE_DATA(op: *mut PyObject) -> *mut Py_UCS1 {
569    PyUnicode_DATA(op) as *mut Py_UCS1
570}
571
572#[cfg(not(any(GraalPy, PyPy)))]
573#[inline]
574pub unsafe fn PyUnicode_2BYTE_DATA(op: *mut PyObject) -> *mut Py_UCS2 {
575    PyUnicode_DATA(op) as *mut Py_UCS2
576}
577
578#[cfg(not(any(GraalPy, PyPy)))]
579#[inline]
580pub unsafe fn PyUnicode_4BYTE_DATA(op: *mut PyObject) -> *mut Py_UCS4 {
581    PyUnicode_DATA(op) as *mut Py_UCS4
582}
583
584#[cfg(not(GraalPy))]
585#[inline]
586pub unsafe fn PyUnicode_GET_LENGTH(op: *mut PyObject) -> Py_ssize_t {
587    debug_assert!(crate::PyUnicode_Check(op) != 0);
588    #[cfg(not(Py_3_12))]
589    debug_assert!(PyUnicode_IS_READY(op) != 0);
590
591    (*(op as *mut PyASCIIObject)).length
592}
593
594// skipped PyUnstable_Unicode_GET_CACHED_HASH
595// skipped PyUnicode_WRITE
596// skipped PyUnicode_READ
597// skipped PyUnicode_READ_CHAR
598// skipped PyUnicode_MAX_CHAR_VALUE
599
600extern_libpython! {
601    #[cfg_attr(PyPy, link_name = "PyPyUnicode_New")]
602    pub fn PyUnicode_New(size: Py_ssize_t, maxchar: Py_UCS4) -> *mut PyObject;
603}
604
605#[cfg(any(Py_3_12, GraalPy))]
606#[inline]
607pub unsafe fn PyUnicode_READY(_op: *mut PyObject) -> c_int {
608    0
609}
610
611#[cfg(not(any(Py_3_12, GraalPy)))]
612#[inline]
613pub unsafe fn PyUnicode_READY(op: *mut PyObject) -> c_int {
614    debug_assert!(crate::PyUnicode_Check(op) != 0);
615
616    if PyUnicode_IS_READY(op) != 0 {
617        0
618    } else {
619        _PyUnicode_Ready(op)
620    }
621}
622
623extern_libpython! {
624    #[cfg(not(any(Py_3_12, GraalPy)))]
625    #[cfg_attr(PyPy, link_name = "_PyPyUnicode_Ready")]
626    fn _PyUnicode_Ready(unicode: *mut PyObject) -> c_int;
627
628    #[cfg(not(PyPy))]
629    pub fn PyUnicode_CopyCharacters(
630        to: *mut PyObject,
631        to_start: Py_ssize_t,
632        from: *mut PyObject,
633        from_start: Py_ssize_t,
634        how_many: Py_ssize_t,
635    ) -> Py_ssize_t;
636
637    #[cfg(not(PyPy))]
638    pub fn PyUnicode_Fill(
639        unicode: *mut PyObject,
640        start: Py_ssize_t,
641        length: Py_ssize_t,
642        fill_char: Py_UCS4,
643    ) -> Py_ssize_t;
644
645    #[cfg(not(Py_3_12))]
646    #[deprecated]
647    #[cfg_attr(PyPy, link_name = "PyPyUnicode_FromUnicode")]
648    pub fn PyUnicode_FromUnicode(u: *const wchar_t, size: Py_ssize_t) -> *mut PyObject;
649
650    #[cfg_attr(PyPy, link_name = "PyPyUnicode_FromKindAndData")]
651    pub fn PyUnicode_FromKindAndData(
652        kind: c_int,
653        buffer: *const c_void,
654        size: Py_ssize_t,
655    ) -> *mut PyObject;
656
657    #[cfg(not(Py_3_12))]
658    #[deprecated]
659    #[cfg_attr(PyPy, link_name = "PyPyUnicode_AsUnicode")]
660    pub fn PyUnicode_AsUnicode(unicode: *mut PyObject) -> *mut wchar_t;
661
662    #[cfg(not(Py_3_12))]
663    #[deprecated]
664    #[cfg_attr(PyPy, link_name = "PyPyUnicode_AsUnicodeAndSize")]
665    pub fn PyUnicode_AsUnicodeAndSize(
666        unicode: *mut PyObject,
667        size: *mut Py_ssize_t,
668    ) -> *mut wchar_t;
669}
670
671#[cfg(Py_3_14)]
672opaque_struct!(pub PyUnicodeWriter);
673
674extern_libpython! {
675    #[cfg(Py_3_14)]
676    pub fn PyUnicodeWriter_Create(length: Py_ssize_t) -> *mut PyUnicodeWriter;
677    #[cfg(Py_3_14)]
678    pub fn PyUnicodeWriter_Discard(writer: *mut PyUnicodeWriter);
679    #[cfg(Py_3_14)]
680    pub fn PyUnicodeWriter_Finish(writer: *mut PyUnicodeWriter) -> *mut PyObject;
681
682    #[cfg(Py_3_14)]
683    pub fn PyUnicodeWriter_WriteChar(writer: *mut PyUnicodeWriter, ch: Py_UCS4) -> c_int;
684    #[cfg(Py_3_14)]
685    pub fn PyUnicodeWriter_WriteUTF8(
686        writer: *mut PyUnicodeWriter,
687        str: *const c_char,
688        size: Py_ssize_t,
689    ) -> c_int;
690    // skipped PyUnicodeWriter_WriteASCII
691    // skipped PyUnicodeWriter_WriteWideChar
692    // skipped PyUnicodeWriter_WriteUCS4
693
694    // skipped PyUnicodeWriter_WriteStr
695    // skipped PyUnicodeWriter_WriteRepr
696    // skipped PyUnicodeWriter_WriteSubstring
697    // skipped PyUnicodeWriter_Format
698    // skipped PyUnicodeWriter_DecodeUTF8Stateful
699}
700
701// skipped private _PyUnicodeWriter
702// skipped private _PyUnicodeWriter_Init
703// skipped private _PyUnicodeWriter_Prepare
704// skipped private _PyUnicodeWriter_PrepareInternal
705// skipped private _PyUnicodeWriter_PrepareKind
706// skipped private _PyUnicodeWriter_PrepareKindInternal
707// skipped private _PyUnicodeWriter_WriteChar
708// skipped private _PyUnicodeWriter_WriteStr
709// skipped private _PyUnicodeWriter_WriteSubstring
710// skipped private _PyUnicodeWriter_WriteASCIIString
711// skipped private _PyUnicodeWriter_WriteLatin1String
712// skipped private _PyUnicodeWriter_Finish
713// skipped private _PyUnicodeWriter_Dealloc
714
715extern_libpython! {
716
717    #[cfg_attr(PyPy, link_name = "PyPyUnicode_AsUTF8")]
718    pub fn PyUnicode_AsUTF8(unicode: *mut PyObject) -> *const c_char;
719
720    // skipped _PyUnicode_AsString
721
722    #[cfg(not(Py_3_11))]
723    #[deprecated(note = "use `PyUnicode_AsEncodedString` instead")]
724    pub fn PyUnicode_Encode(
725        s: *const wchar_t,
726        size: Py_ssize_t,
727        encoding: *const c_char,
728        errors: *const c_char,
729    ) -> *mut PyObject;
730
731    #[cfg(not(Py_3_11))]
732    #[deprecated(note = "use `PyUnicode_AsEncodedString` instead")]
733    pub fn PyUnicode_EncodeUTF7(
734        data: *const wchar_t,
735        length: Py_ssize_t,
736        base64SetO: c_int,
737        base64WhiteSpace: c_int,
738        errors: *const c_char,
739    ) -> *mut PyObject;
740
741    #[cfg(not(Py_3_11))]
742    #[deprecated(note = "use `PyUnicode_AsUTF8String` instead")]
743    #[cfg_attr(PyPy, link_name = "PyPyUnicode_EncodeUTF8")]
744    pub fn PyUnicode_EncodeUTF8(
745        data: *const wchar_t,
746        length: Py_ssize_t,
747        errors: *const c_char,
748    ) -> *mut PyObject;
749
750    #[cfg(not(Py_3_11))]
751    #[deprecated(note = "use `PyUnicode_AsUTF32String` instead")]
752    pub fn PyUnicode_EncodeUTF32(
753        data: *const wchar_t,
754        length: Py_ssize_t,
755        errors: *const c_char,
756        byteorder: c_int,
757    ) -> *mut PyObject;
758
759    #[cfg(not(Py_3_11))]
760    #[deprecated(note = "use `PyUnicode_AsUTF16String` instead")]
761    pub fn PyUnicode_EncodeUTF16(
762        data: *const wchar_t,
763        length: Py_ssize_t,
764        errors: *const c_char,
765        byteorder: c_int,
766    ) -> *mut PyObject;
767
768    #[cfg(not(Py_3_11))]
769    #[deprecated(note = "use `PyUnicode_AsUnicodeEscapeString` instead")]
770    pub fn PyUnicode_EncodeUnicodeEscape(data: *const wchar_t, length: Py_ssize_t)
771        -> *mut PyObject;
772
773    #[cfg(not(Py_3_11))]
774    #[deprecated(note = "use `PyUnicode_AsRawUnicodeEscapeString` instead")]
775    pub fn PyUnicode_EncodeRawUnicodeEscape(
776        data: *const wchar_t,
777        length: Py_ssize_t,
778    ) -> *mut PyObject;
779
780    #[cfg(not(Py_3_11))]
781    #[deprecated(note = "use `PyUnicode_AsLatin1String` instead")]
782    #[cfg_attr(PyPy, link_name = "PyPyUnicode_EncodeLatin1")]
783    pub fn PyUnicode_EncodeLatin1(
784        data: *const wchar_t,
785        length: Py_ssize_t,
786        errors: *const c_char,
787    ) -> *mut PyObject;
788
789    #[cfg(not(Py_3_11))]
790    #[deprecated(note = "use `PyUnicode_AsASCIIString` instead")]
791    #[cfg_attr(PyPy, link_name = "PyPyUnicode_EncodeASCII")]
792    pub fn PyUnicode_EncodeASCII(
793        data: *const wchar_t,
794        length: Py_ssize_t,
795        errors: *const c_char,
796    ) -> *mut PyObject;
797
798    #[cfg(not(Py_3_11))]
799    #[deprecated(note = "use `PyUnicode_AsCharmapString` instead")]
800    pub fn PyUnicode_EncodeCharmap(
801        data: *const wchar_t,
802        length: Py_ssize_t,
803        mapping: *mut PyObject,
804        errors: *const c_char,
805    ) -> *mut PyObject;
806
807    #[cfg(not(Py_3_11))]
808    #[deprecated(note = "use `PyUnicode_Translate` instead")]
809    pub fn PyUnicode_TranslateCharmap(
810        data: *const wchar_t,
811        length: Py_ssize_t,
812        table: *mut PyObject,
813        errors: *const c_char,
814    ) -> *mut PyObject;
815
816    #[cfg(not(Py_3_11))]
817    #[deprecated(note = "use `Py_UNICODE_TODECIMAL` instead")]
818    #[cfg_attr(PyPy, link_name = "PyPyUnicode_EncodeDecimal")]
819    pub fn PyUnicode_EncodeDecimal(
820        s: *mut wchar_t,
821        length: Py_ssize_t,
822        output: *mut c_char,
823        errors: *const c_char,
824    ) -> c_int;
825
826    #[cfg(not(Py_3_11))]
827    #[deprecated(note = "use `Py_UNICODE_TODECIMAL` instead")]
828    #[cfg_attr(PyPy, link_name = "PyPyUnicode_TransformDecimalToASCII")]
829    pub fn PyUnicode_TransformDecimalToASCII(s: *mut wchar_t, length: Py_ssize_t) -> *mut PyObject;
830
831    // skipped _PyUnicode_IsLowercase
832    // skipped _PyUnicode_IsUppercase
833    // skipped _PyUnicode_IsTitlecase
834    // skipped _PyUnicode_IsWhitespace
835    // skipped _PyUnicode_IsLinebreak
836    // skipped _PyUnicode_ToLowercase
837    // skipped _PyUnicode_ToUppercase
838    // skipped _PyUnicode_ToTitlecase
839
840    #[cfg(not(PyPy))]
841    fn _PyUnicode_ToDecimalDigit(ch: Py_UCS4) -> c_int;
842
843    // skipped _PyUnicode_ToDigit
844    // skipped _PyUnicode_ToNumeric
845    // skipped _PyUnicode_IsDecimalDigit
846    // skipped _PyUnicode_IsDigit
847    // skipped _PyUnicode_IsNumeric
848    // skipped _PyUnicode_IsPrintable
849    // skipped _PyUnicode_IsAlpha
850
851}
852
853// skipped _Py_ascii_whitespace
854// skipped Py_UNICODE_ISSPACE
855
856// skipped Py_UNICODE_ISLOWER
857// skipped Py_UNICODE_ISUPPER
858// skipped Py_UNICODE_ISTITLE
859// skipped Py_UNICODE_ISLINEBREAK
860
861// skipped Py_UNICODE_TOLOWER
862// skipped Py_UNICODE_TOUPPER
863// skipped Py_UNICODE_TOTITLE
864
865// skipped Py_UNICODE_ISDECIMAL
866// skipped Py_UNICODE_ISDIGIT
867// skipped Py_UNICODE_ISNUMERIC
868// skipped Py_UNICODE_ISPRINTABLE
869
870#[cfg(not(PyPy))]
871pub unsafe extern "C" fn Py_UNICODE_TODECIMAL(ch: Py_UCS4) -> c_int {
872    _PyUnicode_ToDecimalDigit(ch)
873}
874
875#[cfg(PyPy)]
876extern_libpython! {
877    #[cfg_attr(PyPy, link_name = "PyPy_UNICODE_TODECIMAL")]
878    pub fn Py_UNICODE_TODECIMAL(ch: Py_UCS4) -> c_int;
879}
880
881// skipped Py_UNICODE_TODIGIT
882// skipped Py_UNICODE_TONUMERIC
883
884// skipped Py_UNICODE_ISALPHA
885
886// skipped Py_UNICODE_ISALNUM
887
888// skipped private _PyUnicode_FromId