Skip to content

Commit ef4bea5

Browse files
authored
Add memory_iterator (RustPython#4138)
1 parent 7a688e0 commit ef4bea5

File tree

3 files changed

+69
-6
lines changed

3 files changed

+69
-6
lines changed

vm/src/builtins/memory.rs

Lines changed: 66 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use super::{
2-
PyBytes, PyBytesRef, PyInt, PyListRef, PySlice, PyStr, PyStrRef, PyTuple, PyTupleRef, PyType,
3-
PyTypeRef,
2+
PositionIterInternal, PyBytes, PyBytesRef, PyInt, PyListRef, PySlice, PyStr, PyStrRef, PyTuple,
3+
PyTupleRef, PyType, PyTypeRef,
44
};
55
use crate::{
66
buffer::FormatSpec,
@@ -15,15 +15,20 @@ use crate::{
1515
function::Either,
1616
function::{FuncArgs, OptionalArg, PyComparisonValue},
1717
protocol::{
18-
BufferDescriptor, BufferMethods, PyBuffer, PyMappingMethods, PySequenceMethods, VecBuffer,
18+
BufferDescriptor, BufferMethods, PyBuffer, PyIterReturn, PyMappingMethods,
19+
PySequenceMethods, VecBuffer,
1920
},
2021
sliceable::SequenceIndexOp,
21-
types::{AsBuffer, AsMapping, AsSequence, Comparable, Constructor, Hashable, PyComparisonOp},
22+
types::{
23+
AsBuffer, AsMapping, AsSequence, Comparable, Constructor, Hashable, IterNext,
24+
IterNextIterable, Iterable, PyComparisonOp, Unconstructible,
25+
},
2226
AsObject, Context, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyResult,
2327
TryFromBorrowedObject, TryFromObject, VirtualMachine,
2428
};
2529
use crossbeam_utils::atomic::AtomicCell;
2630
use itertools::Itertools;
31+
use rustpython_common::lock::PyMutex;
2732
use std::{cmp::Ordering, fmt::Debug, mem::ManuallyDrop, ops::Range};
2833

2934
#[derive(FromArgs)]
@@ -61,7 +66,15 @@ impl Constructor for PyMemoryView {
6166
}
6267
}
6368

64-
#[pyclass(with(Hashable, Comparable, AsBuffer, AsMapping, AsSequence, Constructor))]
69+
#[pyclass(with(
70+
Hashable,
71+
Comparable,
72+
AsBuffer,
73+
AsMapping,
74+
AsSequence,
75+
Constructor,
76+
Iterable
77+
))]
6578
impl PyMemoryView {
6679
fn parse_format(format: &str, vm: &VirtualMachine) -> PyResult<FormatSpec> {
6780
FormatSpec::parse(format.as_bytes(), vm)
@@ -1038,7 +1051,8 @@ impl PyPayload for PyMemoryView {
10381051
}
10391052

10401053
pub(crate) fn init(ctx: &Context) {
1041-
PyMemoryView::extend_class(ctx, ctx.types.memoryview_type)
1054+
PyMemoryView::extend_class(ctx, ctx.types.memoryview_type);
1055+
PyMemoryViewIterator::extend_class(ctx, ctx.types.memoryviewiterator_type);
10421056
}
10431057

10441058
fn format_unpack(
@@ -1082,3 +1096,49 @@ fn is_equiv_format(a: &BufferDescriptor, b: &BufferDescriptor) -> bool {
10821096
fn is_equiv_structure(a: &BufferDescriptor, b: &BufferDescriptor) -> bool {
10831097
is_equiv_format(a, b) && is_equiv_shape(a, b)
10841098
}
1099+
1100+
impl Iterable for PyMemoryView {
1101+
fn iter(zelf: PyRef<Self>, vm: &VirtualMachine) -> PyResult {
1102+
Ok(PyMemoryViewIterator {
1103+
internal: PyMutex::new(PositionIterInternal::new(zelf, 0)),
1104+
}
1105+
.into_pyobject(vm))
1106+
}
1107+
}
1108+
1109+
#[pyclass(module = false, name = "memory_iterator")]
1110+
#[derive(Debug)]
1111+
pub struct PyMemoryViewIterator {
1112+
internal: PyMutex<PositionIterInternal<PyRef<PyMemoryView>>>,
1113+
}
1114+
1115+
impl PyPayload for PyMemoryViewIterator {
1116+
fn class(vm: &VirtualMachine) -> &'static Py<PyType> {
1117+
vm.ctx.types.memoryviewiterator_type
1118+
}
1119+
}
1120+
1121+
#[pyclass(with(Constructor, IterNext))]
1122+
impl PyMemoryViewIterator {
1123+
#[pymethod(magic)]
1124+
fn reduce(&self, vm: &VirtualMachine) -> PyTupleRef {
1125+
self.internal
1126+
.lock()
1127+
.builtins_iter_reduce(|x| x.clone().into(), vm)
1128+
}
1129+
}
1130+
impl Unconstructible for PyMemoryViewIterator {}
1131+
1132+
impl IterNextIterable for PyMemoryViewIterator {}
1133+
impl IterNext for PyMemoryViewIterator {
1134+
fn next(zelf: &crate::Py<Self>, vm: &VirtualMachine) -> PyResult<PyIterReturn> {
1135+
zelf.internal.lock().next(|mv, pos| {
1136+
let len = mv.len(vm)?;
1137+
Ok(if pos >= len {
1138+
PyIterReturn::StopIteration(None)
1139+
} else {
1140+
PyIterReturn::Return(mv.getitem_by_idx(pos.try_into().unwrap(), vm)?)
1141+
})
1142+
})
1143+
}
1144+
}

vm/src/types/zoo.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ pub struct TypeZoo {
5858
pub dict_items_type: &'static Py<PyType>,
5959
pub map_type: &'static Py<PyType>,
6060
pub memoryview_type: &'static Py<PyType>,
61+
pub memoryviewiterator_type: &'static Py<PyType>,
6162
pub tuple_type: &'static Py<PyType>,
6263
pub tuple_iterator_type: &'static Py<PyType>,
6364
pub set_type: &'static Py<PyType>,
@@ -160,6 +161,7 @@ impl TypeZoo {
160161
list_iterator_type: list::PyListIterator::init_bare_type(),
161162
list_reverseiterator_type: list::PyListReverseIterator::init_bare_type(),
162163
mappingproxy_type: mappingproxy::PyMappingProxy::init_bare_type(),
164+
memoryviewiterator_type: memory::PyMemoryViewIterator::init_bare_type(),
163165
module_type: module::PyModule::init_bare_type(),
164166
namespace_type: namespace::PyNamespace::init_bare_type(),
165167
range_iterator_type: range::PyRangeIterator::init_bare_type(),

whats_left.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,7 @@ def gen_methods():
200200
"type(range(0).__iter__())",
201201
"type(str().__iter__())",
202202
"type(tuple().__iter__())",
203+
"type(memoryview(bytearray(b'0')).__iter__())",
203204
]
204205

205206
methods = {}

0 commit comments

Comments
 (0)