implement iterator for `Bound` iterator
This commit is contained in:
parent
7d245842d4
commit
d669a943f7
|
@ -16,6 +16,7 @@ use sealed::Sealed;
|
||||||
|
|
||||||
pub(crate) trait FfiPtrExt: Sealed {
|
pub(crate) trait FfiPtrExt: Sealed {
|
||||||
unsafe fn assume_owned_or_err(self, py: Python<'_>) -> PyResult<Bound<'_, PyAny>>;
|
unsafe fn assume_owned_or_err(self, py: Python<'_>) -> PyResult<Bound<'_, PyAny>>;
|
||||||
|
unsafe fn assume_owned_or_opt(self, py: Python<'_>) -> Option<Bound<'_, PyAny>>;
|
||||||
unsafe fn assume_owned(self, py: Python<'_>) -> Bound<'_, PyAny>;
|
unsafe fn assume_owned(self, py: Python<'_>) -> Bound<'_, PyAny>;
|
||||||
|
|
||||||
/// Assumes this pointer is borrowed from a parent object.
|
/// Assumes this pointer is borrowed from a parent object.
|
||||||
|
@ -41,6 +42,11 @@ impl FfiPtrExt for *mut ffi::PyObject {
|
||||||
Bound::from_owned_ptr_or_err(py, self)
|
Bound::from_owned_ptr_or_err(py, self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
unsafe fn assume_owned_or_opt(self, py: Python<'_>) -> Option<Bound<'_, PyAny>> {
|
||||||
|
Bound::from_owned_ptr_or_opt(py, self)
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn assume_owned(self, py: Python<'_>) -> Bound<'_, PyAny> {
|
unsafe fn assume_owned(self, py: Python<'_>) -> Bound<'_, PyAny> {
|
||||||
Bound::from_owned_ptr(py, self)
|
Bound::from_owned_ptr(py, self)
|
||||||
|
|
|
@ -49,18 +49,31 @@ pub struct Bound<'py, T>(Python<'py>, ManuallyDrop<Py<T>>);
|
||||||
|
|
||||||
impl<'py> Bound<'py, PyAny> {
|
impl<'py> Bound<'py, PyAny> {
|
||||||
/// Constructs a new Bound from a pointer. Panics if ptr is null.
|
/// Constructs a new Bound from a pointer. Panics if ptr is null.
|
||||||
|
///
|
||||||
|
/// # Safety
|
||||||
|
///
|
||||||
|
/// `ptr`` must be a valid pointer to a Python object.
|
||||||
pub(crate) unsafe fn from_owned_ptr(py: Python<'py>, ptr: *mut ffi::PyObject) -> Self {
|
pub(crate) unsafe fn from_owned_ptr(py: Python<'py>, ptr: *mut ffi::PyObject) -> Self {
|
||||||
Self(py, ManuallyDrop::new(Py::from_owned_ptr(py, ptr)))
|
Self(py, ManuallyDrop::new(Py::from_owned_ptr(py, ptr)))
|
||||||
}
|
}
|
||||||
|
|
||||||
// /// Constructs a new Bound from a pointer. Returns None if ptr is null.
|
/// Constructs a new Bound from a pointer. Returns None if ptr is null.
|
||||||
// ///
|
///
|
||||||
// /// Safety: ptr must be a valid pointer to a Python object, or NULL.
|
/// # Safety
|
||||||
// pub unsafe fn from_owned_ptr_or_opt(py: Python<'py>, ptr: *mut ffi::PyObject) -> Option<Self> {
|
///
|
||||||
// Py::from_owned_ptr_or_opt(py, ptr).map(|obj| Self(py, ManuallyDrop::new(obj)))
|
/// `ptr`` must be a valid pointer to a Python object, or NULL.
|
||||||
// }
|
pub(crate) unsafe fn from_owned_ptr_or_opt(
|
||||||
|
py: Python<'py>,
|
||||||
|
ptr: *mut ffi::PyObject,
|
||||||
|
) -> Option<Self> {
|
||||||
|
Py::from_owned_ptr_or_opt(py, ptr).map(|obj| Self(py, ManuallyDrop::new(obj)))
|
||||||
|
}
|
||||||
|
|
||||||
/// Constructs a new Bound from a pointer. Returns error if ptr is null.
|
/// Constructs a new Bound from a pointer. Returns error if ptr is null.
|
||||||
|
///
|
||||||
|
/// # Safety
|
||||||
|
///
|
||||||
|
/// `ptr` must be a valid pointer to a Python object, or NULL.
|
||||||
pub(crate) unsafe fn from_owned_ptr_or_err(
|
pub(crate) unsafe fn from_owned_ptr_or_err(
|
||||||
py: Python<'py>,
|
py: Python<'py>,
|
||||||
ptr: *mut ffi::PyObject,
|
ptr: *mut ffi::PyObject,
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use crate::ffi_ptr_ext::FfiPtrExt;
|
use crate::ffi_ptr_ext::FfiPtrExt;
|
||||||
|
use crate::instance::Borrowed;
|
||||||
use crate::py_result_ext::PyResultExt;
|
use crate::py_result_ext::PyResultExt;
|
||||||
use crate::{
|
use crate::{
|
||||||
ffi, AsPyPointer, Bound, PyAny, PyDowncastError, PyErr, PyNativeType, PyResult, PyTypeCheck,
|
ffi, AsPyPointer, Bound, PyAny, PyDowncastError, PyErr, PyNativeType, PyResult, PyTypeCheck,
|
||||||
|
@ -56,21 +57,51 @@ impl<'p> Iterator for &'p PyIterator {
|
||||||
/// Further `next()` calls after an exception occurs are likely
|
/// Further `next()` calls after an exception occurs are likely
|
||||||
/// to repeatedly result in the same exception.
|
/// to repeatedly result in the same exception.
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
let py = self.0.py();
|
Borrowed::<PyIterator>::from_gil_ref(self)
|
||||||
|
.next()
|
||||||
match unsafe { py.from_owned_ptr_or_opt(ffi::PyIter_Next(self.0.as_ptr())) } {
|
.map(|result| result.map(Bound::into_gil_ref))
|
||||||
Some(obj) => Some(Ok(obj)),
|
|
||||||
None => PyErr::take(py).map(Err),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(Py_LIMITED_API))]
|
#[cfg(not(Py_LIMITED_API))]
|
||||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||||
let hint = unsafe { ffi::PyObject_LengthHint(self.0.as_ptr(), 0) };
|
Bound::borrowed_from_gil_ref(self).size_hint()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'py> Iterator for Bound<'py, PyIterator> {
|
||||||
|
type Item = PyResult<Bound<'py, PyAny>>;
|
||||||
|
|
||||||
|
/// Retrieves the next item from an iterator.
|
||||||
|
///
|
||||||
|
/// Returns `None` when the iterator is exhausted.
|
||||||
|
/// If an exception occurs, returns `Some(Err(..))`.
|
||||||
|
/// Further `next()` calls after an exception occurs are likely
|
||||||
|
/// to repeatedly result in the same exception.
|
||||||
|
#[inline]
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
Borrowed::from(&*self).next()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(Py_LIMITED_API))]
|
||||||
|
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||||
|
let hint = unsafe { ffi::PyObject_LengthHint(self.as_ptr(), 0) };
|
||||||
(hint.max(0) as usize, None)
|
(hint.max(0) as usize, None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'py> Borrowed<'_, 'py, PyIterator> {
|
||||||
|
// TODO: this method is on Borrowed so that &'py PyIterator can use this; once that
|
||||||
|
// implementation is deleted this method should be moved to the `Bound<'py, PyIterator> impl
|
||||||
|
fn next(self) -> Option<PyResult<Bound<'py, PyAny>>> {
|
||||||
|
let py = self.py();
|
||||||
|
|
||||||
|
match unsafe { ffi::PyIter_Next(self.as_ptr()).assume_owned_or_opt(py) } {
|
||||||
|
Some(obj) => Some(Ok(obj)),
|
||||||
|
None => PyErr::take(py).map(Err),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl PyTypeCheck for PyIterator {
|
impl PyTypeCheck for PyIterator {
|
||||||
const NAME: &'static str = "Iterator";
|
const NAME: &'static str = "Iterator";
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue