Skip to content

Commit

Permalink
Use _PySet_NextEntry
Browse files Browse the repository at this point in the history
  • Loading branch information
davidhewitt committed Jan 8, 2020
1 parent ec79285 commit f7a4fba
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 11 deletions.
9 changes: 9 additions & 0 deletions src/ffi/setobject.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,4 +60,13 @@ extern "C" {
pub fn PySet_Add(set: *mut PyObject, key: *mut PyObject) -> c_int;
#[cfg_attr(PyPy, link_name = "PyPySet_Pop")]
pub fn PySet_Pop(set: *mut PyObject) -> *mut PyObject;

#[cfg(not(Py_LIMITED_API))]
#[cfg_attr(PyPy, link_name = "_PySet_NextEntry")]
pub fn _PySet_NextEntry(
set: *mut PyObject,
pos: *mut Py_ssize_t,
key: *mut *mut PyObject,
hash: *mut super::Py_hash_t,
) -> c_int;
}
52 changes: 41 additions & 11 deletions src/types/set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ use crate::ffi;
use crate::instance::PyNativeType;
use crate::internal_tricks::Unsendable;
use crate::object::PyObject;
use crate::objectprotocol::ObjectProtocol;
use crate::types::{PyAny, PyIterator};
use crate::types::PyAny;
use crate::AsPyPointer;
use crate::Python;
use crate::{ToBorrowedObject, ToPyObject};
Expand Down Expand Up @@ -98,12 +97,40 @@ impl PySet {
}
}

#[cfg(not(Py_LIMITED_API))]
pub struct PySetIterator<'py> {
set: &'py super::PyAny,
pos: isize,
}

#[cfg(not(Py_LIMITED_API))]
impl<'py> Iterator for PySetIterator<'py> {
type Item = &'py super::PyAny;

#[inline]
fn next(&mut self) -> Option<Self::Item> {
unsafe {
let mut key: *mut ffi::PyObject = std::ptr::null_mut();
let mut hash: ffi::Py_hash_t = 0;
if ffi::_PySet_NextEntry(self.set.as_ptr(), &mut self.pos, &mut key, &mut hash) != 0 {
Some(self.set.py().from_borrowed_ptr(key))
} else {
None
}
}
}
}

#[cfg(not(Py_LIMITED_API))]
impl<'a> std::iter::IntoIterator for &'a PySet {
type Item = PyResult<&'a PyAny>;
type IntoIter = PyIterator<'a>;
type Item = &'a PyAny;
type IntoIter = PySetIterator<'a>;

fn into_iter(self) -> Self::IntoIter {
self.iter().expect("Failed to get set iterator")
PySetIterator {
set: self.as_ref(),
pos: 0,
}
}
}

Expand Down Expand Up @@ -178,13 +205,16 @@ impl PyFrozenSet {
})
}
}

#[cfg(not(Py_LIMITED_API))]
impl<'a> std::iter::IntoIterator for &'a PyFrozenSet {
type Item = PyResult<&'a PyAny>;
type IntoIter = PyIterator<'a>;
type Item = &'a PyAny;
type IntoIter = PySetIterator<'a>;

fn into_iter(self) -> Self::IntoIter {
self.iter().expect("Failed to get frozen set iterator")
PySetIterator {
set: self.as_ref(),
pos: 0,
}
}
}

Expand Down Expand Up @@ -294,7 +324,7 @@ mod test {

// intoiterator iteration
for el in set {
assert_eq!(1i32, el.unwrap().extract().unwrap());
assert_eq!(1i32, el.extract().unwrap());
}
}

Expand Down Expand Up @@ -340,7 +370,7 @@ mod test {

// intoiterator iteration
for el in set {
assert_eq!(1i32, el.unwrap().extract::<i32>().unwrap());
assert_eq!(1i32, el.extract::<i32>().unwrap());
}
}
}

0 comments on commit f7a4fba

Please sign in to comment.