1
1
use std:: { fmt:: Debug , iter:: FromIterator } ;
2
2
3
- use super :: {
3
+ use crate :: obj:: objbytes:: { PyBytes , PyBytesRef } ;
4
+ use crate :: obj:: objlist:: { PyList , PyListRef } ;
5
+ use crate :: obj:: {
4
6
objsequence:: get_pos, objsequence:: get_slice_range, objsequence:: SequenceIndex ,
5
7
objslice:: PySliceRef , objstr:: PyString , objtype:: PyClassRef ,
6
8
} ;
7
- use crate :: common:: hash:: PyHash ;
8
- use crate :: obj:: objbytes:: { PyBytes , PyBytesRef } ;
9
- use crate :: obj:: objlist:: { PyList , PyListRef } ;
10
- use crate :: pyobject:: IdProtocol ;
11
9
use crate :: pyobject:: {
12
- PyClassImpl , PyContext , PyObjectRef , PyRef , PyResult , PyThreadingConstraint , PyValue ,
13
- TypeProtocol ,
10
+ IdProtocol , PyClassImpl , PyContext , PyObjectRef , PyRef , PyResult , PyThreadingConstraint ,
11
+ PyValue , TypeProtocol ,
14
12
} ;
15
13
use crate :: slots:: { Bufferable , Hashable } ;
16
14
use crate :: VirtualMachine ;
17
15
use crate :: { bytesinner:: try_as_bytes, pyobject:: IntoPyObject } ;
16
+ use crate :: { common:: hash:: PyHash , pyobject:: PyComparisonValue } ;
18
17
use crossbeam_utils:: atomic:: AtomicCell ;
19
18
use num_bigint:: BigInt ;
20
19
use num_traits:: { One , Signed , ToPrimitive , Zero } ;
@@ -40,7 +39,6 @@ pub struct BufferOptions {
40
39
pub len : usize ,
41
40
pub itemsize : usize ,
42
41
pub contiguous : bool ,
43
- // pub range: Range<usize>,
44
42
// TODO: support multiple dimension array
45
43
pub ndim : usize ,
46
44
// TODO: support format
@@ -142,17 +140,20 @@ impl PyMemoryView {
142
140
. map ( |_|PyString :: from ( & self . options . format ) )
143
141
}
144
142
145
- fn getitem_by_idx ( & self , i : isize , vm : & VirtualMachine ) ->PyResult {
143
+ fn get_pos ( & self , i : isize ) ->Option < usize > {
146
144
let len =self . options . len ;
147
- let i =
148
- get_pos ( i, len) . ok_or_else ( || vm. new_index_error ( "index out of range" . to_owned ( ) ) ) ?;
149
- // let i = (self.start as isize + i as isize * self.step) as usize;
150
- let i =if self . step <0 {
145
+ let i =get_pos ( i, len) ?;
146
+ Some ( if self . step <0 {
151
147
self . stop -( -self . step ) as usize * i +self . step as usize
152
148
} else {
153
149
self . start +self . step as usize * i
154
- } ;
150
+ } )
151
+ }
155
152
153
+ fn getitem_by_idx ( & self , i : isize , vm : & VirtualMachine ) ->PyResult {
154
+ let i =self
155
+ . get_pos ( i)
156
+ . ok_or_else ( || vm. new_index_error ( "index out of range" . to_owned ( ) ) ) ?;
156
157
unpack_value ( self . buffer . as_bytes ( ) [ i] , & self . options . format , vm)
157
158
}
158
159
@@ -198,30 +199,10 @@ impl PyMemoryView {
198
199
let range =get_slice_range ( & start, & stop, len) ;
199
200
let range = zelf. start + range. start ..zelf. start + range. end ;
200
201
201
- // let step: BigInt = step * self.step;
202
- // newlen will be 0 if step is overflowed, in that case step should not change the behavour
202
+ // newlen will be 0 if step is overflowed
203
203
let newstep = newstep. to_isize ( ) . unwrap_or ( -1 ) ;
204
204
205
- // let (start, stop, step, newlen) = if range.start >= range.end {
206
- // (0, 0, 1, 0)
207
- // } else if step.is_positive() {
208
- // let start = self.start + range.start;
209
- // match step.to_isize() {
210
- // Some(step) => {
211
- // let newlen = len / step as usize;
212
- // (start, start + newlen, step, newlen)
213
- // },
214
- // None => (start, start + 1, 1, 1),
215
- // }
216
- // } else {
217
- // match step.to_isize() {
218
- // Some(step) => (range.end - 1, step, len / step.abs() as usize),
219
- // None => (range.end - 1, -1, 1),
220
- // }
221
- // };
222
-
223
205
let obj = zelf. obj . clone ( ) ;
224
- // let buffer = try_buffer_from_object(self.obj.clone(), vm)?;
225
206
let buffer =Box :: new ( zelf. clone ( ) ) ;
226
207
let options = zelf. options . clone ( ) ;
227
208
@@ -244,7 +225,6 @@ impl PyMemoryView {
244
225
#[ pymethod( magic) ]
245
226
fn getitem ( zelf : PyRef < Self > , needle : SequenceIndex , vm : & VirtualMachine ) ->PyResult {
246
227
zelf. try_not_released ( vm) ?;
247
- // self.obj.get_item(needle, vm)
248
228
match needle{
249
229
SequenceIndex :: Int ( i) => zelf. getitem_by_idx ( i, vm) ,
250
230
SequenceIndex :: Slice ( slice) =>Self :: getitem_by_slice ( zelf, slice, vm) ,
@@ -256,17 +236,41 @@ impl PyMemoryView {
256
236
self . try_not_released ( vm) . map ( |_|self . options . len )
257
237
}
258
238
239
+ fn get_contiguous_bytes ( & self ) ->Option < BorrowedValue < [ u8 ] > > {
240
+ if self . options . contiguous {
241
+ Some ( BorrowedValue :: map ( self . buffer . as_bytes ( ) , |x|{
242
+ & x[ self . start ..self . stop ]
243
+ } ) )
244
+ } else {
245
+ None
246
+ }
247
+ }
248
+
259
249
#[ pymethod]
260
250
fn tobytes ( & self , vm : & VirtualMachine ) ->PyResult < PyBytesRef > {
261
- self . try_not_released ( vm)
262
- . map ( |_|PyBytes :: from ( self . buffer . as_bytes ( ) . to_vec ( ) ) . into_ref ( vm) )
251
+ self . try_not_released ( vm) ?;
252
+ if let Some ( bytes) =self . get_contiguous_bytes ( ) {
253
+ Ok ( PyBytes :: from ( bytes. to_vec ( ) ) . into_ref ( vm) )
254
+ } else {
255
+ let bytes =& * self . buffer . as_bytes ( ) ;
256
+ let bytes =( 0 ..self . options . len )
257
+ . map ( |i|self . get_pos ( ias isize ) . unwrap ( ) )
258
+ . map ( |i| bytes[ i] )
259
+ . collect :: < Vec < u8 > > ( ) ;
260
+ Ok ( PyBytes :: from ( bytes) . into_ref ( vm) )
261
+ }
263
262
}
264
263
265
264
#[ pymethod]
266
265
fn tolist ( & self , vm : & VirtualMachine ) ->PyResult < PyListRef > {
267
266
self . try_not_released ( vm) . map ( |_|{
268
- PyList :: from_iter ( self . buffer . as_bytes ( ) . iter ( ) . map ( |x| x. into_pyobject ( vm) ) )
269
- . into_ref ( vm)
267
+ let bytes =& * self . buffer . as_bytes ( ) ;
268
+ PyList :: from_iter (
269
+ ( 0 ..self . options . len )
270
+ . map ( |i|self . get_pos ( ias isize ) . unwrap ( ) )
271
+ . map ( |i| bytes[ i] . into_pyobject ( vm) ) ,
272
+ )
273
+ . into_ref ( vm)
270
274
} )
271
275
}
272
276
@@ -296,6 +300,39 @@ impl PyMemoryView {
296
300
format ! ( "<memory at 0x{:x}>" , zelf. get_id( ) )
297
301
}
298
302
}
303
+
304
+ #[ pymethod( magic) ]
305
+ fn eq (
306
+ zelf : PyRef < Self > ,
307
+ other : PyObjectRef ,
308
+ vm : & VirtualMachine ,
309
+ ) ->PyResult < PyComparisonValue > {
310
+ zelf. try_not_released ( vm) ?;
311
+ if zelf. is ( & other) {
312
+ return Ok ( PyComparisonValue :: Implemented ( true ) ) ;
313
+ }
314
+ let options_cmp = |a : & BufferOptions , b : & BufferOptions | ->bool {
315
+ a. len == b. len && a. itemsize == b. itemsize && a. format == b. format
316
+ } ;
317
+ if let Some ( other) = other. payload_if_subclass :: < PyMemoryView > ( vm) {
318
+ if options_cmp ( & zelf. options , & other. options ) {
319
+ let a = zelf. tolist ( vm) ?;
320
+ let b = other. tolist ( vm) ?;
321
+ if vm. bool_eq ( a. into_object ( ) , b. into_object ( ) ) ?{
322
+ return Ok ( PyComparisonValue :: Implemented ( true ) ) ;
323
+ }
324
+ }
325
+ return Ok ( PyComparisonValue :: Implemented ( false ) ) ;
326
+ }
327
+ if let Ok ( buffer) =try_buffer_from_object ( other, vm) {
328
+ let options = buffer. get_options ( ) ;
329
+ if options_cmp ( & zelf. options , & options) &&( * * ( zelf. tobytes ( vm) ?) ==* buffer. as_bytes ( ) )
330
+ {
331
+ return Ok ( PyComparisonValue :: Implemented ( true ) ) ;
332
+ }
333
+ }
334
+ Ok ( PyComparisonValue :: Implemented ( false ) )
335
+ }
299
336
}
300
337
301
338
impl Drop for PyMemoryView {
@@ -305,14 +342,13 @@ impl Drop for PyMemoryView {
305
342
}
306
343
307
344
impl Bufferable for PyMemoryView {
308
- fn get_buffer ( zelf : PyRef < Self > , vm : & VirtualMachine ) ->PyResult < Box < dyn BufferProtocol > > {
309
- try_buffer_from_object ( zelf . obj . clone ( ) , vm )
345
+ fn get_buffer ( zelf : PyRef < Self > , _vm : & VirtualMachine ) ->PyResult < Box < dyn BufferProtocol > > {
346
+ Ok ( Box :: new ( zelf ) )
310
347
}
311
348
}
312
349
313
350
impl BufferProtocol for PyMemoryViewRef {
314
351
fn get_options ( & self ) ->BufferOptions {
315
- // use options from ourself
316
352
self . options . clone ( )
317
353
}
318
354