Skip to content

Commit b0183b2

Browse files
authored
Merge pull request RustPython#2383 from qingshi163/memoryview-cast
Implement Memoryview cast
2 parents 0786e4c + 06ff997 commit b0183b2

File tree

2 files changed

+44
-2
lines changed

2 files changed

+44
-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: 44 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>);
@@ -654,6 +655,7 @@ impl PyMemoryView {
654655
fn toreadonly(zelf: PyRef<Self>, vm: &VirtualMachine) -> PyResult<PyRef<Self>> {
655656
zelf.try_not_released(vm)?;
656657
let buffer = BufferRef(Box::new(zelf.clone()));
658+
zelf.exports.fetch_add(1);
657659
Ok(PyMemoryView {
658660
obj: zelf.obj.clone(),
659661
buffer,
@@ -703,6 +705,48 @@ impl PyMemoryView {
703705
bytes_to_hex(bytes, sep, bytes_per_sep, vm)
704706
}
705707

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

0 commit comments

Comments
 (0)