Merge pull request #1399 from davidhewitt/pystring-to-string

pystring: use PyUnicode_AsUTF8AndSize always from Python 3.10 and up
This commit is contained in:
David Hewitt 2021-01-23 16:01:09 +00:00 committed by GitHub
commit f2bf58ea37
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 22 additions and 21 deletions

View file

@ -143,14 +143,16 @@ extern "C" {
#[cfg_attr(PyPy, link_name = "PyPyUnicode_FromOrdinal")]
pub fn PyUnicode_FromOrdinal(ordinal: c_int) -> *mut PyObject;
pub fn PyUnicode_ClearFreeList() -> c_int;
#[cfg(not(Py_LIMITED_API))]
#[cfg(any(not(Py_LIMITED_API), Py_3_10))]
#[cfg(Py_3_7)]
#[cfg_attr(PyPy, link_name = "PyPyUnicode_AsUTF8AndSize")]
pub fn PyUnicode_AsUTF8AndSize(unicode: *mut PyObject, size: *mut Py_ssize_t) -> *const c_char;
#[cfg(not(Py_3_7))]
#[cfg_attr(PyPy, link_name = "PyPyUnicode_AsUTF8AndSize")]
pub fn PyUnicode_AsUTF8AndSize(unicode: *mut PyObject, size: *mut Py_ssize_t) -> *mut c_char;
#[cfg(not(Py_LIMITED_API))]
#[cfg(Py_3_7)]
#[cfg_attr(PyPy, link_name = "PyPyUnicode_AsUTF8")]
pub fn PyUnicode_AsUTF8(unicode: *mut PyObject) -> *const c_char;
#[cfg(not(Py_3_7))]
#[cfg_attr(PyPy, link_name = "PyPyUnicode_AsUTF8")]

View file

@ -44,27 +44,26 @@ impl PyString {
/// (containing unpaired surrogates).
#[inline]
pub fn to_str(&self) -> PyResult<&str> {
#[cfg(not(Py_LIMITED_API))]
unsafe {
let mut size: ffi::Py_ssize_t = 0;
let data = ffi::PyUnicode_AsUTF8AndSize(self.as_ptr(), &mut size) as *const u8;
if data.is_null() {
Err(PyErr::fetch(self.py()))
} else {
let slice = std::slice::from_raw_parts(data, size as usize);
Ok(std::str::from_utf8_unchecked(slice))
let utf8_slice = {
cfg_if::cfg_if! {
if #[cfg(any(not(Py_LIMITED_API), Py_3_10))] {
// PyUnicode_AsUTF8AndSize only available on limited API from Python 3.10 and up.
let mut size: ffi::Py_ssize_t = 0;
let data = unsafe { ffi::PyUnicode_AsUTF8AndSize(self.as_ptr(), &mut size) };
if data.is_null() {
return Err(PyErr::fetch(self.py()));
} else {
unsafe { std::slice::from_raw_parts(data as *const u8, size as usize) }
}
} else {
let bytes = unsafe {
self.py().from_owned_ptr_or_err::<PyBytes>(ffi::PyUnicode_AsUTF8String(self.as_ptr()))?
};
bytes.as_bytes()
}
}
}
#[cfg(Py_LIMITED_API)]
unsafe {
let data = ffi::PyUnicode_AsUTF8String(self.as_ptr());
if data.is_null() {
Err(PyErr::fetch(self.py()))
} else {
let bytes = self.py().from_owned_ptr::<PyBytes>(data);
Ok(std::str::from_utf8_unchecked(bytes.as_bytes()))
}
}
};
Ok(unsafe { std::str::from_utf8_unchecked(utf8_slice) })
}
/// Converts the `PyString` into a Rust string.