1
- use super :: objtype:: PyTypeRef ;
2
1
use std:: { fmt:: Debug , ops:: Deref } ;
3
2
3
+ use crate :: common:: borrow:: { BorrowedValue , BorrowedValueMut } ;
4
+ use crate :: common:: hash:: PyHash ;
4
5
use crate :: obj:: objbytes:: { PyBytes , PyBytesRef } ;
5
6
use crate :: obj:: objlist:: { PyList , PyListRef } ;
6
- use crate :: obj:: { objslice:: PySliceRef , objstr:: PyStr } ;
7
+ use crate :: obj:: objslice:: PySliceRef ;
8
+ use crate :: obj:: objstr:: PyStr ;
9
+ use crate :: obj:: objtype:: PyTypeRef ;
7
10
use crate :: pyobject:: {
8
- IdProtocol , PyClassImpl , PyContext , PyObjectRef , PyRef , PyResult , PyThreadingConstraint ,
9
- PyValue , TypeProtocol ,
11
+ IdProtocol , PyClassImpl , PyComparisonValue , PyContext , PyObjectRef , PyRef , PyResult ,
12
+ PyThreadingConstraint , PyValue , TypeProtocol ,
10
13
} ;
11
- use crate :: sliceable:: { saturate_range, wrap_index, SequenceIndex } ;
14
+ use crate :: sliceable:: { convert_slice , saturate_range, wrap_index, SequenceIndex } ;
12
15
use crate :: slots:: { BufferProtocol , Comparable , Hashable , PyComparisonOp } ;
13
16
use crate :: stdlib:: pystruct:: _struct:: FormatSpec ;
14
17
use crate :: VirtualMachine ;
15
- use crate :: { common:: hash:: PyHash , pyobject:: PyComparisonValue } ;
16
18
use crossbeam_utils:: atomic:: AtomicCell ;
17
19
use itertools:: Itertools ;
18
20
use num_bigint:: BigInt ;
19
21
use num_traits:: { One , Signed , ToPrimitive , Zero } ;
20
- use rustpython_common:: borrow:: { BorrowedValue , BorrowedValueMut } ;
21
22
22
23
#[ derive( Debug ) ]
23
24
pub struct BufferRef ( Box < dyn Buffer > ) ;
@@ -62,6 +63,10 @@ pub trait Buffer: Debug + PyThreadingConstraint {
62
63
Some ( self . obj_bytes_mut ( ) )
63
64
}
64
65
66
+ fn to_contiguous ( & self ) -> Vec < u8 > {
67
+ self . obj_bytes ( ) . to_vec ( )
68
+ }
69
+
65
70
fn try_resizable ( & self , vm : & VirtualMachine ) -> PyResult < ( ) > {
66
71
if self . is_resizable ( ) {
67
72
Ok ( ( ) )
@@ -371,26 +376,154 @@ impl PyMemoryView {
371
376
}
372
377
}
373
378
379
+ fn setitem_by_idx (
380
+ zelf : PyRef < Self > ,
381
+ i : isize ,
382
+ value : PyObjectRef ,
383
+ vm : & VirtualMachine ,
384
+ ) -> PyResult < ( ) > {
385
+ let i = zelf
386
+ . get_pos ( i)
387
+ . ok_or_else ( || vm. new_index_error ( "index out of range" . to_owned ( ) ) ) ?;
388
+ let itemsize = zelf. options . itemsize ;
389
+ let data = zelf. format_spec . pack ( & [ value] , vm) ?;
390
+ zelf. obj_bytes_mut ( ) [ i..i + itemsize] . copy_from_slice ( & data) ;
391
+ Ok ( ( ) )
392
+ }
393
+
394
+ fn setitem_by_slice (
395
+ zelf : PyRef < Self > ,
396
+ slice : PySliceRef ,
397
+ items : PyObjectRef ,
398
+ vm : & VirtualMachine ,
399
+ ) -> PyResult < ( ) > {
400
+ let items = try_buffer_from_object ( vm, & items) ?;
401
+ let options = items. get_options ( ) ;
402
+ let len = options. len ;
403
+ let itemsize = options. itemsize ;
404
+
405
+ if itemsize != zelf. options . itemsize {
406
+ return Err ( vm. new_type_error ( format ! (
407
+ "memoryview: invalid type for format '{}'" ,
408
+ zelf. options. format
409
+ ) ) ) ;
410
+ }
411
+
412
+ let diff_err = || {
413
+ Err ( vm. new_value_error (
414
+ "memoryview assignment: lvalue and rvalue have different structures" . to_owned ( ) ,
415
+ ) )
416
+ } ;
417
+
418
+ if options. format != zelf. options . format {
419
+ return diff_err ( ) ;
420
+ }
421
+
422
+ let ( range, step, is_negative_step) = convert_slice ( & slice, zelf. options . len , vm) ?;
423
+
424
+ let bytes = items. to_contiguous ( ) ;
425
+ assert_eq ! ( bytes. len( ) , len * itemsize) ;
426
+
427
+ if !is_negative_step && step == Some ( 1 ) {
428
+ if range. end - range. start != len {
429
+ return diff_err ( ) ;
430
+ }
431
+
432
+ if let Some ( mut buffer) = zelf. as_contiguous_mut ( ) {
433
+ buffer[ range. start * itemsize..range. end * itemsize] . copy_from_slice ( & bytes) ;
434
+ return Ok ( ( ) ) ;
435
+ }
436
+ }
437
+
438
+ if let Some ( step) = step {
439
+ let slicelen = if range. end > range. start {
440
+ ( range. end - range. start - 1 ) / step + 1
441
+ } else {
442
+ 0
443
+ } ;
444
+
445
+ if slicelen != len {
446
+ return diff_err ( ) ;
447
+ }
448
+
449
+ let indexes = if is_negative_step {
450
+ itertools:: Either :: Left ( range. rev ( ) . step_by ( step) )
451
+ } else {
452
+ itertools:: Either :: Right ( range. step_by ( step) )
453
+ } ;
454
+
455
+ let item_index = ( 0 ..len) . step_by ( itemsize) ;
456
+
457
+ let mut buffer = zelf. obj_bytes_mut ( ) ;
458
+
459
+ indexes
460
+ . map ( |i| zelf. get_pos ( i as isize ) . unwrap ( ) )
461
+ . zip ( item_index)
462
+ . for_each ( |( i, item_i) | {
463
+ buffer[ i..i + itemsize] . copy_from_slice ( & bytes[ item_i..item_i + itemsize] ) ;
464
+ } ) ;
465
+ Ok ( ( ) )
466
+ } else {
467
+ let slicelen = if range. start < range. end { 1 } else { 0 } ;
468
+ if match len {
469
+ 0 => slicelen == 0 ,
470
+ 1 => {
471
+ let mut buffer = zelf. obj_bytes_mut ( ) ;
472
+ let i = zelf. get_pos ( range. start as isize ) . unwrap ( ) ;
473
+ buffer[ i..i + itemsize] . copy_from_slice ( & bytes) ;
474
+ true
475
+ }
476
+ _ => false ,
477
+ } {
478
+ Ok ( ( ) )
479
+ } else {
480
+ diff_err ( )
481
+ }
482
+ }
483
+ }
484
+
485
+ #[ pymethod( magic) ]
486
+ fn setitem (
487
+ zelf : PyRef < Self > ,
488
+ needle : SequenceIndex ,
489
+ value : PyObjectRef ,
490
+ vm : & VirtualMachine ,
491
+ ) -> PyResult < ( ) > {
492
+ zelf. try_not_released ( vm) ?;
493
+ if zelf. options . readonly {
494
+ return Err ( vm. new_type_error ( "cannot modify read-only memory" . to_owned ( ) ) ) ;
495
+ }
496
+ match needle {
497
+ SequenceIndex :: Int ( i) => Self :: setitem_by_idx ( zelf, i, value, vm) ,
498
+ SequenceIndex :: Slice ( slice) => Self :: setitem_by_slice ( zelf, slice, value, vm) ,
499
+ }
500
+ }
501
+
374
502
#[ pymethod( magic) ]
375
503
fn len ( & self , vm : & VirtualMachine ) -> PyResult < usize > {
376
504
self . try_not_released ( vm) . map ( |_| self . options . len )
377
505
}
378
506
379
- #[ pymethod]
380
- fn tobytes ( zelf : PyRef < Self > , vm : & VirtualMachine ) -> PyResult < PyBytesRef > {
381
- zelf. try_not_released ( vm) ?;
507
+ fn to_bytes_vec ( zelf : & PyRef < Self > ) -> Vec < u8 > {
382
508
if let Some ( bytes) = zelf. as_contiguous ( ) {
383
- Ok ( PyBytes :: from ( bytes. to_vec ( ) ) . into_ref ( vm ) )
509
+ bytes. to_vec ( )
384
510
} else {
385
511
let bytes = & * zelf. obj_bytes ( ) ;
386
- let bytes = ( 0 ..zelf. options . len )
512
+ let len = zelf. options . len ;
513
+ let itemsize = zelf. options . itemsize ;
514
+ ( 0 ..len)
387
515
. map ( |i| zelf. get_pos ( i as isize ) . unwrap ( ) )
388
- . flat_map ( |i| ( i..i + zelf. options . itemsize ) . map ( |i| bytes[ i] ) )
389
- . collect :: < Vec < u8 > > ( ) ;
390
- Ok ( PyBytes :: from ( bytes) . into_ref ( vm) )
516
+ . flat_map ( |i| bytes[ i..i + itemsize] . to_vec ( ) )
517
+ . collect ( )
391
518
}
392
519
}
393
520
521
+ #[ pymethod]
522
+ fn tobytes ( zelf : PyRef < Self > , vm : & VirtualMachine ) -> PyResult < PyBytesRef > {
523
+ zelf. try_not_released ( vm) ?;
524
+ Ok ( PyBytes :: from ( Self :: to_bytes_vec ( & zelf) ) . into_ref ( vm) )
525
+ }
526
+
394
527
#[ pymethod]
395
528
fn tolist ( zelf : PyRef < Self > , vm : & VirtualMachine ) -> PyResult < PyListRef > {
396
529
zelf. try_not_released ( vm) ?;
@@ -433,7 +566,7 @@ impl PyMemoryView {
433
566
. into_ref ( vm) )
434
567
}
435
568
436
- #[ pymethod]
569
+ #[ pymethod( magic ) ]
437
570
fn repr ( zelf : PyRef < Self > ) -> String {
438
571
if zelf. released . load ( ) {
439
572
format ! ( "<released memory at 0x{:x}>" , zelf. get_id( ) )
@@ -443,10 +576,12 @@ impl PyMemoryView {
443
576
}
444
577
445
578
fn eq ( zelf : & PyRef < Self > , other : & PyObjectRef , vm : & VirtualMachine ) -> PyResult < bool > {
446
- zelf. try_not_released ( vm) ?;
447
579
if zelf. is ( other) {
448
580
return Ok ( true ) ;
449
581
}
582
+ if zelf. released . load ( ) {
583
+ return Ok ( false ) ;
584
+ }
450
585
let options_cmp = |a : & BufferOptions , b : & BufferOptions | -> bool {
451
586
a. len == b. len && a. itemsize == b. itemsize
452
587
} ;
@@ -535,6 +670,10 @@ impl Buffer for PyMemoryViewRef {
535
670
& mut x[ self . start ..self . stop ]
536
671
} ) )
537
672
}
673
+
674
+ fn to_contiguous ( & self ) -> Vec < u8 > {
675
+ PyMemoryView :: to_bytes_vec ( self )
676
+ }
538
677
}
539
678
540
679
impl Comparable for PyMemoryView {
0 commit comments