Skip to content

Commit

Permalink
PyListIter
Browse files Browse the repository at this point in the history
  • Loading branch information
ijl committed Mar 20, 2023
1 parent f6175cd commit 3bf0d87
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 4 deletions.
44 changes: 44 additions & 0 deletions src/ffi/list.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// SPDX-License-Identifier: (Apache-2.0 OR MIT)

use std::ptr::NonNull;

pub struct PyListIter {
obj: *mut pyo3_ffi::PyListObject,
len: usize,
pos: usize,
}

impl PyListIter {
#[inline]
pub fn from_pyobject(obj: *mut pyo3_ffi::PyObject) -> Self {
unsafe {
PyListIter {
obj: obj as *mut pyo3_ffi::PyListObject,
len: ffi!(Py_SIZE(obj)) as usize,
pos: 0,
}
}
}
}

impl Iterator for PyListIter {
type Item = NonNull<pyo3_ffi::PyObject>;

#[inline(always)]
fn next(&mut self) -> Option<Self::Item> {
if self.pos == self.len {
None
} else {
let elem = unsafe { *((*self.obj).ob_item).add(self.pos) };
self.pos += 1;
Some(nonnull!(elem))
}
}

fn size_hint(&self) -> (usize, Option<usize>) {
(self.len, Some(self.len))
}
}

#[cfg(feature = "trusted_len")]
unsafe impl std::iter::TrustedLen for PyListIter {}
2 changes: 2 additions & 0 deletions src/ffi/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@
mod buffer;
mod bytes;
mod dict;
mod list;
mod pytype;

pub use buffer::*;
pub use bytes::*;
pub use dict::*;
pub use list::PyListIter;
pub use pytype::*;
7 changes: 3 additions & 4 deletions src/serialize/list.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// SPDX-License-Identifier: (Apache-2.0 OR MIT)

use crate::ffi::PyListIter;
use crate::opt::*;
use crate::serialize::serializer::*;

Expand Down Expand Up @@ -41,11 +42,9 @@ impl Serialize for ListSerializer {
serializer.serialize_seq(Some(0)).unwrap().end()
} else {
let mut seq = serializer.serialize_seq(None).unwrap();
for i in 0..=ffi!(Py_SIZE(self.ptr)) as usize - 1 {
let elem =
unsafe { *((*(self.ptr as *mut pyo3_ffi::PyListObject)).ob_item).add(i) };
for elem in PyListIter::from_pyobject(self.ptr) {
let value = PyObjectSerializer::new(
elem,
elem.as_ptr(),
self.opts,
self.default_calls,
self.recursion,
Expand Down

0 comments on commit 3bf0d87

Please sign in to comment.