Skip to content

Commit 13e901c

Browse files
authored
Merge pull request #3043 from youknowone/pybuffer2
subtle pybuffer updates
2 parents 7761845 + 5befe49 commit 13e901c

File tree

2 files changed

+49
-55
lines changed

2 files changed

+49
-55
lines changed

vm/src/builtins/memory.rs

Lines changed: 47 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
use crate::buffer::{BufferOptions, PyBuffer, PyBufferInternal};
2-
use crate::builtins::bytes::{PyBytes, PyBytesRef};
3-
use crate::builtins::list::{PyList, PyListRef};
4-
use crate::builtins::pystr::{PyStr, PyStrRef};
5-
use crate::builtins::pytype::PyTypeRef;
62
use crate::builtins::slice::PySliceRef;
3+
use crate::builtins::{PyBytes, PyBytesRef, PyList, PyListRef, PyStr, PyStrRef, PyTypeRef};
74
use crate::bytesinner::bytes_to_hex;
85
use crate::common::{
96
borrow::{BorrowedValue, BorrowedValueMut},
@@ -12,7 +9,7 @@ use crate::common::{
129
rc::PyRc,
1310
};
1411
use crate::function::{FuncArgs, OptionalArg};
15-
use crate::sliceable::{convert_slice, saturate_range, wrap_index, SequenceIndex};
12+
use crate::sliceable::{convert_slice, wrap_index, SequenceIndex};
1613
use crate::slots::{AsBuffer, Comparable, Hashable, PyComparisonOp, SlotConstructor};
1714
use crate::stdlib::pystruct::_struct::FormatSpec;
1815
use crate::utils::Either;
@@ -22,8 +19,7 @@ use crate::{
2219
};
2320
use crossbeam_utils::atomic::AtomicCell;
2421
use itertools::Itertools;
25-
use num_bigint::BigInt;
26-
use num_traits::{One, Signed, ToPrimitive, Zero};
22+
use num_traits::ToPrimitive;
2723
use std::fmt::Debug;
2824
use std::ops::Deref;
2925

@@ -37,7 +33,7 @@ pub struct PyMemoryViewNewArgs {
3733
#[derive(Debug)]
3834
pub struct PyMemoryView {
3935
buffer: PyBuffer,
40-
pub(crate) released: AtomicCell<bool>,
36+
released: AtomicCell<bool>,
4137
// start should always less or equal to the stop
4238
// start and stop pointing to the memory index not slice index
4339
// if length is not zero than [start, stop)
@@ -61,6 +57,24 @@ impl SlotConstructor for PyMemoryView {
6157

6258
#[pyimpl(with(Hashable, Comparable, AsBuffer, SlotConstructor))]
6359
impl PyMemoryView {
60+
#[cfg(debug_assertions)]
61+
fn validate(self) -> Self {
62+
let options = &self.buffer.options;
63+
let bytes_len = options.len * options.itemsize;
64+
let buffer_len = self.buffer.internal.obj_bytes().len();
65+
let t1 = self.stop - self.start == bytes_len;
66+
let t2 = buffer_len >= self.stop;
67+
let t3 = buffer_len >= self.start + bytes_len;
68+
assert!(t1);
69+
assert!(t2);
70+
assert!(t3);
71+
self
72+
}
73+
#[cfg(not(debug_assertions))]
74+
fn validate(self) -> Self {
75+
self
76+
}
77+
6478
fn parse_format(format: &str, vm: &VirtualMachine) -> PyResult<FormatSpec> {
6579
FormatSpec::parse(format, vm)
6680
}
@@ -80,7 +94,8 @@ impl PyMemoryView {
8094
step: 1,
8195
format_spec,
8296
hash: OnceCell::new(),
83-
})
97+
}
98+
.validate())
8499
}
85100

86101
pub fn from_buffer_range(
@@ -99,7 +114,8 @@ impl PyMemoryView {
99114
step: 1,
100115
format_spec,
101116
hash: OnceCell::new(),
102-
})
117+
}
118+
.validate())
103119
}
104120

105121
fn as_contiguous(&self) -> Option<BorrowedValue<[u8]>> {
@@ -238,25 +254,20 @@ impl PyMemoryView {
238254

239255
fn getitem_by_slice(zelf: PyRef<Self>, slice: PySliceRef, vm: &VirtualMachine) -> PyResult {
240256
// slicing a memoryview return a new memoryview
241-
let start = slice.start_index(vm)?;
242-
let stop = slice.stop_index(vm)?;
243-
let step = slice.step_index(vm)?.unwrap_or_else(BigInt::one);
244-
if step.is_zero() {
245-
return Err(vm.new_value_error("slice step cannot be zero".to_owned()));
246-
}
247-
let newstep: BigInt = step.clone() * zelf.step;
248257
let len = zelf.buffer.options.len;
258+
let (range, step, is_negative_step) = convert_slice(&slice, len, vm)?;
259+
let abs_step = step.unwrap();
260+
let step = if is_negative_step {
261+
-(abs_step as isize)
262+
} else {
263+
abs_step as isize
264+
};
265+
let newstep = step * zelf.step;
249266
let itemsize = zelf.buffer.options.itemsize;
250267

251268
let format_spec = zelf.format_spec.clone();
252269

253-
if newstep == BigInt::one() {
254-
let range = saturate_range(&start, &stop, len);
255-
let range = if range.end < range.start {
256-
range.start..range.start
257-
} else {
258-
range
259-
};
270+
if newstep == 1 {
260271
let newlen = range.end - range.start;
261272
let start = zelf.start + range.start * itemsize;
262273
let stop = zelf.start + range.end * itemsize;
@@ -273,38 +284,11 @@ impl PyMemoryView {
273284
format_spec,
274285
hash: OnceCell::new(),
275286
}
287+
.validate()
276288
.into_object(vm));
277289
}
278290

279-
let (start, stop) = if step.is_negative() {
280-
(
281-
stop.map(|x| {
282-
if x == -BigInt::one() {
283-
len + BigInt::one()
284-
} else {
285-
x + 1
286-
}
287-
}),
288-
start.map(|x| {
289-
if x == -BigInt::one() {
290-
BigInt::from(len)
291-
} else {
292-
x + 1
293-
}
294-
}),
295-
)
296-
} else {
297-
(start, stop)
298-
};
299-
300-
let range = saturate_range(&start, &stop, len);
301-
let newlen = if range.end > range.start {
302-
// overflow is not possible as dividing a positive integer
303-
((range.end - range.start - 1) / step.abs())
304-
.to_usize()
305-
.unwrap()
306-
+ 1
307-
} else {
291+
if range.start >= range.end {
308292
return Ok(PyMemoryView {
309293
buffer: zelf.buffer.clone_with_options(BufferOptions {
310294
len: 0,
@@ -318,9 +302,16 @@ impl PyMemoryView {
318302
format_spec,
319303
hash: OnceCell::new(),
320304
}
305+
.validate()
321306
.into_object(vm));
322307
};
323308

309+
// overflow is not possible as dividing a positive integer
310+
let newlen = ((range.end - range.start - 1) / abs_step)
311+
.to_usize()
312+
.unwrap()
313+
+ 1;
314+
324315
// newlen will be 0 if step is overflowed
325316
let newstep = newstep.to_isize().unwrap_or(-1);
326317

@@ -348,6 +339,7 @@ impl PyMemoryView {
348339
format_spec,
349340
hash: OnceCell::new(),
350341
}
342+
.validate()
351343
.into_object(vm))
352344
}
353345

@@ -541,6 +533,7 @@ impl PyMemoryView {
541533
hash: OnceCell::new(),
542534
..*zelf
543535
}
536+
.validate()
544537
.into_ref(vm))
545538
}
546539

@@ -610,6 +603,7 @@ impl PyMemoryView {
610603
hash: OnceCell::new(),
611604
..*zelf
612605
}
606+
.validate()
613607
.into_ref(vm))
614608
}
615609

vm/src/stdlib/io.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -893,7 +893,7 @@ mod _io {
893893
// TODO: loop if write() raises an interrupt
894894
let res = vm.call_method(raw, "write", (memobj.clone(),));
895895

896-
memobj.released.store(true);
896+
memobj.release();
897897
self.buffer = std::mem::take(&mut writebuf.data.lock());
898898

899899
res?
@@ -1132,7 +1132,7 @@ mod _io {
11321132
let res =
11331133
vm.call_method(self.raw.as_ref().unwrap(), "readinto", (memobj.clone(),));
11341134

1135-
memobj.released.store(true);
1135+
memobj.release();
11361136
std::mem::swap(v, &mut readbuf.data.lock());
11371137

11381138
res?

0 commit comments

Comments
 (0)