1
1
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 ;
6
2
use crate :: builtins:: slice:: PySliceRef ;
3
+ use crate :: builtins:: { PyBytes , PyBytesRef , PyList , PyListRef , PyStr , PyStrRef , PyTypeRef } ;
7
4
use crate :: bytesinner:: bytes_to_hex;
8
5
use crate :: common:: {
9
6
borrow:: { BorrowedValue , BorrowedValueMut } ,
@@ -12,7 +9,7 @@ use crate::common::{
12
9
rc:: PyRc ,
13
10
} ;
14
11
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 } ;
16
13
use crate :: slots:: { AsBuffer , Comparable , Hashable , PyComparisonOp , SlotConstructor } ;
17
14
use crate :: stdlib:: pystruct:: _struct:: FormatSpec ;
18
15
use crate :: utils:: Either ;
@@ -22,8 +19,7 @@ use crate::{
22
19
} ;
23
20
use crossbeam_utils:: atomic:: AtomicCell ;
24
21
use itertools:: Itertools ;
25
- use num_bigint:: BigInt ;
26
- use num_traits:: { One , Signed , ToPrimitive , Zero } ;
22
+ use num_traits:: ToPrimitive ;
27
23
use std:: fmt:: Debug ;
28
24
use std:: ops:: Deref ;
29
25
@@ -37,7 +33,7 @@ pub struct PyMemoryViewNewArgs {
37
33
#[ derive( Debug ) ]
38
34
pub struct PyMemoryView {
39
35
buffer : PyBuffer ,
40
- pub ( crate ) released : AtomicCell < bool > ,
36
+ released : AtomicCell < bool > ,
41
37
// start should always less or equal to the stop
42
38
// start and stop pointing to the memory index not slice index
43
39
// if length is not zero than [start, stop)
@@ -61,6 +57,24 @@ impl SlotConstructor for PyMemoryView {
61
57
62
58
#[ pyimpl( with( Hashable , Comparable , AsBuffer , SlotConstructor ) ) ]
63
59
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
+
64
78
fn parse_format ( format : & str , vm : & VirtualMachine ) -> PyResult < FormatSpec > {
65
79
FormatSpec :: parse ( format, vm)
66
80
}
@@ -80,7 +94,8 @@ impl PyMemoryView {
80
94
step : 1 ,
81
95
format_spec,
82
96
hash : OnceCell :: new ( ) ,
83
- } )
97
+ }
98
+ . validate ( ) )
84
99
}
85
100
86
101
pub fn from_buffer_range (
@@ -99,7 +114,8 @@ impl PyMemoryView {
99
114
step : 1 ,
100
115
format_spec,
101
116
hash : OnceCell :: new ( ) ,
102
- } )
117
+ }
118
+ . validate ( ) )
103
119
}
104
120
105
121
fn as_contiguous ( & self ) -> Option < BorrowedValue < [ u8 ] > > {
@@ -238,25 +254,20 @@ impl PyMemoryView {
238
254
239
255
fn getitem_by_slice ( zelf : PyRef < Self > , slice : PySliceRef , vm : & VirtualMachine ) -> PyResult {
240
256
// 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 ;
248
257
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 ;
249
266
let itemsize = zelf. buffer . options . itemsize ;
250
267
251
268
let format_spec = zelf. format_spec . clone ( ) ;
252
269
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 {
260
271
let newlen = range. end - range. start ;
261
272
let start = zelf. start + range. start * itemsize;
262
273
let stop = zelf. start + range. end * itemsize;
@@ -273,38 +284,11 @@ impl PyMemoryView {
273
284
format_spec,
274
285
hash : OnceCell :: new ( ) ,
275
286
}
287
+ . validate ( )
276
288
. into_object ( vm) ) ;
277
289
}
278
290
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 {
308
292
return Ok ( PyMemoryView {
309
293
buffer : zelf. buffer . clone_with_options ( BufferOptions {
310
294
len : 0 ,
@@ -318,9 +302,16 @@ impl PyMemoryView {
318
302
format_spec,
319
303
hash : OnceCell :: new ( ) ,
320
304
}
305
+ . validate ( )
321
306
. into_object ( vm) ) ;
322
307
} ;
323
308
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
+
324
315
// newlen will be 0 if step is overflowed
325
316
let newstep = newstep. to_isize ( ) . unwrap_or ( -1 ) ;
326
317
@@ -348,6 +339,7 @@ impl PyMemoryView {
348
339
format_spec,
349
340
hash : OnceCell :: new ( ) ,
350
341
}
342
+ . validate ( )
351
343
. into_object ( vm) )
352
344
}
353
345
@@ -541,6 +533,7 @@ impl PyMemoryView {
541
533
hash : OnceCell :: new ( ) ,
542
534
..* zelf
543
535
}
536
+ . validate ( )
544
537
. into_ref ( vm) )
545
538
}
546
539
@@ -610,6 +603,7 @@ impl PyMemoryView {
610
603
hash : OnceCell :: new ( ) ,
611
604
..* zelf
612
605
}
606
+ . validate ( )
613
607
. into_ref ( vm) )
614
608
}
615
609
0 commit comments