Skip to content

Commit 44048f6

Browse files
committed
Implement memoryview cast
1 parent d177b8f commit 44048f6

File tree

2 files changed

+41
-2
lines changed

2 files changed

+41
-2
lines changed

Lib/test/test_memoryview.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -384,8 +384,6 @@ def test_toreadonly(self):
384384
mm.release()
385385
m.tolist()
386386

387-
# TODO: RUSTPYTHON
388-
@unittest.expectedFailure
389387
def test_issue22668(self):
390388
a = array.array('H', [256, 256, 256, 256])
391389
x = memoryview(a)

vm/src/builtins/memory.rs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ use crossbeam_utils::atomic::AtomicCell;
2323
use itertools::Itertools;
2424
use num_bigint::BigInt;
2525
use num_traits::{One, Signed, ToPrimitive, Zero};
26+
use rustpython_common::borrow::BorrowValue;
2627

2728
#[derive(Debug)]
2829
pub struct BufferRef(Box<dyn Buffer>);
@@ -703,6 +704,46 @@ impl PyMemoryView {
703704
bytes_to_hex(bytes, sep, bytes_per_sep, vm)
704705
}
705706

707+
// TODO: support cast shape
708+
#[pymethod]
709+
fn cast(zelf: PyRef<Self>, format: PyStrRef, vm: &VirtualMachine) -> PyResult<PyRef<Self>> {
710+
zelf.try_not_released(vm)?;
711+
if !zelf.options.contiguous {
712+
return Err(vm.new_type_error(
713+
"memoryview: casts are restricted to C-contiguous views".to_owned(),
714+
));
715+
}
716+
717+
let format_spec = Self::parse_format(format.borrow_value(), vm)?;
718+
let itemsize = format_spec.size();
719+
720+
if zelf.options.len % itemsize != 0 {
721+
return Err(
722+
vm.new_type_error("memoryview: length is not a multiple of itemsize".to_owned())
723+
);
724+
}
725+
726+
let buffer = BufferRef(Box::new(zelf.clone()));
727+
zelf.exports.fetch_add(1);
728+
729+
Ok(PyMemoryView {
730+
obj: zelf.obj.clone(),
731+
buffer,
732+
options: BufferOptions {
733+
itemsize,
734+
format: format.to_string().into(),
735+
..zelf.options.clone()
736+
},
737+
released: AtomicCell::new(false),
738+
stop: zelf.stop + itemsize - zelf.options.itemsize,
739+
exports: AtomicCell::new(0),
740+
format_spec,
741+
hash: OnceCell::new(),
742+
..*zelf
743+
}
744+
.into_ref(vm))
745+
}
746+
706747
fn eq(zelf: &PyRef<Self>, other: &PyObjectRef, vm: &VirtualMachine) -> PyResult<bool> {
707748
if zelf.is(other) {
708749
return Ok(true);

0 commit comments

Comments
 (0)