Use CPython stable APIs for implementing tuples.
Refs #1125 Reduces the number of compilation failures with `--features abi3` from 56 to 53.
This commit is contained in:
parent
3151c4876e
commit
958ce796e9
|
@ -42,7 +42,7 @@ impl PyTuple {
|
||||||
pub fn len(&self) -> usize {
|
pub fn len(&self) -> usize {
|
||||||
unsafe {
|
unsafe {
|
||||||
// non-negative Py_ssize_t should always fit into Rust uint
|
// non-negative Py_ssize_t should always fit into Rust uint
|
||||||
ffi::PyTuple_GET_SIZE(self.as_ptr()) as usize
|
ffi::PyTuple_Size(self.as_ptr()) as usize
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,8 +62,7 @@ impl PyTuple {
|
||||||
/// Takes a slice of the tuple from `low` to the end and returns it as a new tuple.
|
/// Takes a slice of the tuple from `low` to the end and returns it as a new tuple.
|
||||||
pub fn split_from(&self, low: isize) -> &PyTuple {
|
pub fn split_from(&self, low: isize) -> &PyTuple {
|
||||||
unsafe {
|
unsafe {
|
||||||
let ptr =
|
let ptr = ffi::PyTuple_GetSlice(self.as_ptr(), low, self.len() as Py_ssize_t);
|
||||||
ffi::PyTuple_GetSlice(self.as_ptr(), low, ffi::PyTuple_GET_SIZE(self.as_ptr()));
|
|
||||||
self.py().from_owned_ptr(ptr)
|
self.py().from_owned_ptr(ptr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -75,11 +74,14 @@ impl PyTuple {
|
||||||
assert!(index < self.len());
|
assert!(index < self.len());
|
||||||
unsafe {
|
unsafe {
|
||||||
self.py()
|
self.py()
|
||||||
.from_borrowed_ptr(ffi::PyTuple_GET_ITEM(self.as_ptr(), index as Py_ssize_t))
|
.from_borrowed_ptr(ffi::PyTuple_GetItem(self.as_ptr(), index as Py_ssize_t))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `self` as a slice of objects.
|
/// Returns `self` as a slice of objects.
|
||||||
|
///
|
||||||
|
/// Not available when compiled with Py_LIMITED_API.
|
||||||
|
#[cfg(not(Py_LIMITED_API))]
|
||||||
pub fn as_slice(&self) -> &[&PyAny] {
|
pub fn as_slice(&self) -> &[&PyAny] {
|
||||||
// This is safe because &PyAny has the same memory layout as *mut ffi::PyObject,
|
// This is safe because &PyAny has the same memory layout as *mut ffi::PyObject,
|
||||||
// and because tuples are immutable.
|
// and because tuples are immutable.
|
||||||
|
@ -93,16 +95,18 @@ impl PyTuple {
|
||||||
/// Returns an iterator over the tuple items.
|
/// Returns an iterator over the tuple items.
|
||||||
pub fn iter(&self) -> PyTupleIterator {
|
pub fn iter(&self) -> PyTupleIterator {
|
||||||
PyTupleIterator {
|
PyTupleIterator {
|
||||||
slice: self.as_slice(),
|
tuple: self,
|
||||||
index: 0,
|
index: 0,
|
||||||
|
length: self.len(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Used by `PyTuple::iter()`.
|
/// Used by `PyTuple::iter()`.
|
||||||
pub struct PyTupleIterator<'a> {
|
pub struct PyTupleIterator<'a> {
|
||||||
slice: &'a [&'a PyAny],
|
tuple: &'a PyTuple,
|
||||||
index: usize,
|
index: usize,
|
||||||
|
length: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Iterator for PyTupleIterator<'a> {
|
impl<'a> Iterator for PyTupleIterator<'a> {
|
||||||
|
@ -110,8 +114,8 @@ impl<'a> Iterator for PyTupleIterator<'a> {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn next(&mut self) -> Option<&'a PyAny> {
|
fn next(&mut self) -> Option<&'a PyAny> {
|
||||||
if self.index < self.slice.len() {
|
if self.index < self.length {
|
||||||
let item = self.slice[self.index];
|
let item = self.tuple.get_item(self.index);
|
||||||
self.index += 1;
|
self.index += 1;
|
||||||
Some(item)
|
Some(item)
|
||||||
} else {
|
} else {
|
||||||
|
@ -172,10 +176,9 @@ macro_rules! tuple_conversion ({$length:expr,$(($refN:ident, $n:tt, $T:ident)),+
|
||||||
fn extract(obj: &'s PyAny) -> PyResult<Self>
|
fn extract(obj: &'s PyAny) -> PyResult<Self>
|
||||||
{
|
{
|
||||||
let t = <PyTuple as PyTryFrom>::try_from(obj)?;
|
let t = <PyTuple as PyTryFrom>::try_from(obj)?;
|
||||||
let slice = t.as_slice();
|
|
||||||
if t.len() == $length {
|
if t.len() == $length {
|
||||||
Ok((
|
Ok((
|
||||||
$(slice[$n].extract::<$T>()?,)+
|
$(t.get_item($n).extract::<$T>()?,)+
|
||||||
))
|
))
|
||||||
} else {
|
} else {
|
||||||
Err(wrong_tuple_length(t, $length))
|
Err(wrong_tuple_length(t, $length))
|
||||||
|
@ -296,4 +299,19 @@ mod test {
|
||||||
assert_eq!(i + 1, item.extract().unwrap());
|
assert_eq!(i + 1, item.extract().unwrap());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(not(Py_LIMITED_API))]
|
||||||
|
fn test_as_slice() {
|
||||||
|
let gil = Python::acquire_gil();
|
||||||
|
let py = gil.python();
|
||||||
|
let ob = (1, 2, 3).to_object(py);
|
||||||
|
let tuple = <PyTuple as PyTryFrom>::try_from(ob.as_ref(py)).unwrap();
|
||||||
|
|
||||||
|
let slice = tuple.as_slice();
|
||||||
|
assert_eq!(3, slice.len());
|
||||||
|
assert_eq!(1, slice[0].extract().unwrap());
|
||||||
|
assert_eq!(2, slice[1].extract().unwrap());
|
||||||
|
assert_eq!(3, slice[2].extract().unwrap());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue