|
6 | 6 | const SIGN_MASK: usize = 3;
|
7 | 7 | #[cfg(Py_3_12)]
|
8 | 8 | const SIGN_ZERO: usize = 1;
|
| 9 | + |
| 10 | +#[cfg(Py_3_12)] |
| 11 | +#[allow(non_upper_case_globals)] |
| 12 | +const _PyLong_NON_SIZE_BITS: usize = 3; |
| 13 | + |
9 | 14 | #[cfg(Py_3_12)]
|
10 |
| -const SIGN_POSITIVE: usize = 0; |
| 15 | +#[repr(C)] |
| 16 | +struct _PyLongValue { |
| 17 | + pub lv_tag: usize, |
| 18 | + pub ob_digit: u32, |
| 19 | +} |
11 | 20 |
|
12 | 21 | #[cfg(Py_3_12)]
|
13 |
| -#[allow(dead_code)] |
| 22 | +#[repr(C)] |
14 | 23 | struct PyLongObject {
|
15 | 24 | pub ob_refcnt: pyo3_ffi::Py_ssize_t,
|
16 | 25 | pub ob_type: *mut pyo3_ffi::PyTypeObject,
|
17 |
| - pub lv_tag: usize, |
18 |
| - pub ob_digit: u8, |
| 26 | + pub long_value: _PyLongValue, |
19 | 27 | }
|
20 | 28 |
|
21 | 29 | #[cfg(Py_3_12)]
|
| 30 | +#[inline(always)] |
22 | 31 | pub fn pylong_is_zero(ptr: *mut pyo3_ffi::PyObject) -> bool {
|
23 |
| - unsafe { (*(ptr as *mut PyLongObject)).lv_tag & SIGN_MASK == SIGN_ZERO } |
| 32 | + unsafe { (*(ptr as *mut PyLongObject)).long_value.lv_tag & SIGN_MASK == SIGN_ZERO } |
24 | 33 | }
|
25 | 34 |
|
26 | 35 | #[cfg(not(Py_3_12))]
|
| 36 | +#[inline(always)] |
27 | 37 | pub fn pylong_is_zero(ptr: *mut pyo3_ffi::PyObject) -> bool {
|
28 | 38 | unsafe { (*(ptr as *mut pyo3_ffi::PyVarObject)).ob_size == 0 }
|
29 | 39 | }
|
30 | 40 |
|
31 | 41 | #[cfg(Py_3_12)]
|
| 42 | +#[inline(always)] |
32 | 43 | pub fn pylong_is_unsigned(ptr: *mut pyo3_ffi::PyObject) -> bool {
|
33 |
| - unsafe { (*(ptr as *mut PyLongObject)).lv_tag & SIGN_MASK == SIGN_POSITIVE } |
| 44 | + unsafe { |
| 45 | + 1 - (((*(ptr as *mut PyLongObject)).long_value.lv_tag & _PyLong_NON_SIZE_BITS) as isize) > 0 |
| 46 | + } |
34 | 47 | }
|
35 | 48 |
|
36 | 49 | #[cfg(not(Py_3_12))]
|
| 50 | +#[inline(always)] |
37 | 51 | pub fn pylong_is_unsigned(ptr: *mut pyo3_ffi::PyObject) -> bool {
|
38 | 52 | unsafe { (*(ptr as *mut pyo3_ffi::PyVarObject)).ob_size > 0 }
|
39 | 53 | }
|
| 54 | + |
| 55 | +#[cfg(Py_3_12)] |
| 56 | +#[inline(always)] |
| 57 | +fn pylong_is_compact(ptr: *mut pyo3_ffi::PyObject) -> bool { |
| 58 | + unsafe { (*(ptr as *mut PyLongObject)).long_value.lv_tag < (2 << _PyLong_NON_SIZE_BITS) } |
| 59 | +} |
| 60 | + |
| 61 | +#[cfg(Py_3_12)] |
| 62 | +#[inline(always)] |
| 63 | +pub fn pylong_value_unsigned(ptr: *mut pyo3_ffi::PyObject) -> u64 { |
| 64 | + if pylong_is_compact(ptr) == true { |
| 65 | + unsafe { (*(ptr as *mut PyLongObject)).long_value.ob_digit as u64 } |
| 66 | + } else { |
| 67 | + ffi!(PyLong_AsUnsignedLongLong(ptr)) |
| 68 | + } |
| 69 | +} |
| 70 | + |
| 71 | +#[cfg(not(Py_3_12))] |
| 72 | +#[inline(always)] |
| 73 | +pub fn pylong_value_unsigned(ptr: *mut pyo3_ffi::PyObject) -> u64 { |
| 74 | + ffi!(PyLong_AsUnsignedLongLong(ptr)) |
| 75 | +} |
| 76 | + |
| 77 | +#[cfg(not(Py_3_12))] |
| 78 | +#[inline(always)] |
| 79 | +pub fn pylong_value_signed(ptr: *mut pyo3_ffi::PyObject) -> i64 { |
| 80 | + ffi!(PyLong_AsLongLong(ptr)) |
| 81 | +} |
| 82 | + |
| 83 | +#[cfg(Py_3_12)] |
| 84 | +#[inline(always)] |
| 85 | +pub fn pylong_value_signed(ptr: *mut pyo3_ffi::PyObject) -> i64 { |
| 86 | + if pylong_is_compact(ptr) == true { |
| 87 | + unsafe { |
| 88 | + let sign = 1 - ((*(ptr as *mut PyLongObject)).long_value.lv_tag & SIGN_MASK) as i64; |
| 89 | + sign * (*(ptr as *mut PyLongObject)).long_value.ob_digit as i64 |
| 90 | + } |
| 91 | + } else { |
| 92 | + ffi!(PyLong_AsLongLong(ptr)) |
| 93 | + } |
| 94 | +} |
0 commit comments