Skip to content

Commit 908b239

Browse files
authored
Refactor and new sequence traits, generic sequence operation (RustPython#3445)
* refactor sequence generic mutable sequence item equal op * sequence generic for pydeque * replace usize::MAX with Optioned * sequence op for array * fix overflow error instead memory error for index overflow * fixup * optimize reserve vec for imul
1 parent a53451b commit 908b239

13 files changed

Lines changed: 434 additions & 450 deletions

File tree

Cargo.lock

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

stdlib/src/array.rs

Lines changed: 19 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ mod array {
2323
BufferDescriptor, BufferMethods, BufferResizeGuard, PyBuffer, PyIterReturn,
2424
PyMappingMethods,
2525
},
26+
sequence::{SequenceMutOp, SequenceOp},
2627
sliceable::{PySliceableSequence, PySliceableSequenceMut, SaturatedSlice, SequenceIndex},
2728
types::{
2829
AsBuffer, AsMapping, Comparable, Constructor, IterNext, IterNextIterable, Iterable,
@@ -387,34 +388,24 @@ mod array {
387388
}
388389
}
389390

390-
fn mul(&self, counter: usize) -> Self {
391+
fn mul(&self, value: isize, vm: &VirtualMachine) -> PyResult<Self> {
391392
match self {
392393
$(ArrayContentType::$n(v) => {
393-
let elements = v.repeat(counter);
394-
ArrayContentType::$n(elements)
394+
// MemoryError instead Overflow Error, hard to says it is right
395+
// but it is how cpython doing right now
396+
let elements = v.mul(vm, value).map_err(|_| vm.new_memory_error("".to_owned()))?;
397+
Ok(ArrayContentType::$n(elements))
395398
})*
396399
}
397400
}
398401

399-
fn clear(&mut self) {
402+
fn imul(&mut self, value: isize, vm: &VirtualMachine) -> PyResult<()> {
400403
match self {
401-
$(ArrayContentType::$n(v) => v.clear(),)*
402-
}
403-
}
404-
405-
fn imul(&mut self, counter: usize) {
406-
if counter == 0 {
407-
self.clear();
408-
} else if counter != 1 {
409-
match self {
410-
$(ArrayContentType::$n(v) => {
411-
let old = v.clone();
412-
v.reserve((counter - 1) * old.len());
413-
for _ in 1..counter {
414-
v.extend(&old);
415-
}
416-
})*
417-
}
404+
$(ArrayContentType::$n(v) => {
405+
// MemoryError instead Overflow Error, hard to says it is right
406+
// but it is how cpython doing right now
407+
v.imul(vm, value).map_err(|_| vm.new_memory_error("".to_owned()))
408+
})*
418409
}
419410
}
420411

@@ -742,8 +733,7 @@ mod array {
742733
fn extend(zelf: PyRef<Self>, obj: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
743734
let mut w = zelf.try_resizable(vm)?;
744735
if zelf.is(&obj) {
745-
w.imul(2);
746-
Ok(())
736+
w.imul(2, vm)
747737
} else if let Some(array) = obj.payload::<PyArray>() {
748738
w.iadd(&*array.read(), vm)
749739
} else {
@@ -856,7 +846,7 @@ mod array {
856846
if n < 0 {
857847
return Err(vm.new_value_error("negative count".to_owned()));
858848
}
859-
let n = vm.check_repeat_or_memory_error(itemsize, n)?;
849+
let n = vm.check_repeat_or_overflow_error(itemsize, n)?;
860850
let nbytes = n * itemsize;
861851

862852
let b = vm.call_method(&f, "read", (nbytes,))?;
@@ -1044,7 +1034,7 @@ mod array {
10441034
vm: &VirtualMachine,
10451035
) -> PyResult<PyRef<Self>> {
10461036
if zelf.is(&other) {
1047-
zelf.try_resizable(vm)?.imul(2);
1037+
zelf.try_resizable(vm)?.imul(2, vm)?;
10481038
} else if let Some(other) = other.payload::<PyArray>() {
10491039
zelf.try_resizable(vm)?.iadd(&*other.read(), vm)?;
10501040
} else {
@@ -1059,14 +1049,14 @@ mod array {
10591049
#[pymethod(name = "__rmul__")]
10601050
#[pymethod(magic)]
10611051
fn mul(&self, value: isize, vm: &VirtualMachine) -> PyResult<PyRef<Self>> {
1062-
let value = vm.check_repeat_or_memory_error(self.len(), value)?;
1063-
Ok(Self::from(self.read().mul(value)).into_ref(vm))
1052+
self.read()
1053+
.mul(value, vm)
1054+
.map(|x| Self::from(x).into_ref(vm))
10641055
}
10651056

10661057
#[pymethod(magic)]
10671058
fn imul(zelf: PyRef<Self>, value: isize, vm: &VirtualMachine) -> PyResult<PyRef<Self>> {
1068-
let value = vm.check_repeat_or_memory_error(zelf.len(), value)?;
1069-
zelf.try_resizable(vm)?.imul(value);
1059+
zelf.try_resizable(vm)?.imul(value, vm)?;
10701060
Ok(zelf)
10711061
}
10721062

vm/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ adler32 = "1.0.3"
6969
flate2 = "1.0.20"
7070
once_cell = "1"
7171
memoffset = "0.6"
72+
optional = "0.5"
7273

7374
# RustPython crates implementing functionality based on CPython
7475
sre-engine = "0.1.2"

vm/src/builtins/bytearray.rs

Lines changed: 5 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,7 @@ impl PyByteArray {
285285
}
286286
}
287287

288-
fn irepeat(zelf: &crate::PyObjectView<Self>, n: usize, vm: &VirtualMachine) -> PyResult<()> {
288+
fn irepeat(zelf: &crate::PyObjectView<Self>, n: isize, vm: &VirtualMachine) -> PyResult<()> {
289289
if n == 1 {
290290
return Ok(());
291291
}
@@ -300,19 +300,8 @@ impl PyByteArray {
300300
};
301301
}
302302
};
303-
let elements = &mut w.elements;
304303

305-
if n == 0 {
306-
elements.clear();
307-
} else if n != 1 {
308-
let old = elements.clone();
309-
310-
elements.reserve((n - 1) * old.len());
311-
for _ in 1..n {
312-
elements.extend(&old);
313-
}
314-
}
315-
Ok(())
304+
w.imul(n, vm)
316305
}
317306

318307
#[pymethod]
@@ -635,14 +624,13 @@ impl PyByteArray {
635624
#[pymethod(name = "__rmul__")]
636625
#[pymethod(magic)]
637626
fn mul(&self, value: isize, vm: &VirtualMachine) -> PyResult<Self> {
638-
vm.check_repeat_or_memory_error(self.len(), value)
639-
.map(|value| self.inner().repeat(value).into())
627+
self.inner().mul(value, vm).map(|x| x.into())
640628
}
641629

642630
#[pymethod(magic)]
643631
fn imul(zelf: PyRef<Self>, value: isize, vm: &VirtualMachine) -> PyResult<PyRef<Self>> {
644-
vm.check_repeat_or_memory_error(zelf.len(), value)
645-
.and_then(|value| Self::irepeat(&zelf, value, vm).map(|_| zelf))
632+
Self::irepeat(&zelf, value, vm)?;
633+
Ok(zelf)
646634
}
647635

648636
#[pymethod(name = "__mod__")]

vm/src/builtins/bytes.rs

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -461,14 +461,9 @@ impl PyBytes {
461461
// This only works for `bytes` itself, not its subclasses.
462462
return Ok(zelf);
463463
}
464-
// todo: map err to overflow.
465-
vm.check_repeat_or_memory_error(zelf.inner.len(), value)
466-
.map(|value| {
467-
let bytes: PyBytes = zelf.inner.repeat(value).into();
468-
bytes.into_ref(vm)
469-
})
470-
// see issue 45044 on b.p.o.
471-
.map_err(|_| vm.new_overflow_error("repeated bytes are too long".to_owned()))
464+
zelf.inner
465+
.mul(value, vm)
466+
.map(|x| Self::from(x).into_ref(vm))
472467
}
473468

474469
#[pymethod(name = "__mod__")]

0 commit comments

Comments
 (0)