@@ -3,14 +3,20 @@ pub(crate) use mmap::make_module;
33
44#[ pymodule]
55mod mmap {
6- use crate :: common:: lock:: { PyMutex , PyMutexGuard } ;
6+ use crate :: common:: {
7+ borrow:: { BorrowedValue , BorrowedValueMut } ,
8+ lock:: { MapImmutable , PyMutex , PyMutexGuard } ,
9+ } ;
710 use crate :: vm:: {
811 builtins:: { PyBytes , PyBytesRef , PyInt , PyIntRef , PyTypeRef } ,
9- byte:: value_from_object,
12+ byte:: { bytes_from_object , value_from_object} ,
1013 function:: { ArgBytesLike , FuncArgs , OptionalArg } ,
11- sliceable:: saturate_index,
12- types:: Constructor ,
13- AsObject , FromArgs , PyObject , PyObjectRef , PyPayload , PyRef , PyResult ,
14+ protocol:: {
15+ BufferDescriptor , BufferMethods , PyBuffer , PyMappingMethods , PySequenceMethods ,
16+ } ,
17+ sliceable:: { saturate_index, wrap_index, SaturatedSlice , SequenceIndex } ,
18+ types:: { AsBuffer , AsMapping , AsSequence , Constructor } ,
19+ AsObject , FromArgs , Py , PyObject , PyObjectRef , PyPayload , PyRef , PyResult ,
1420 TryFromBorrowedObject , VirtualMachine ,
1521 } ;
1622 use crossbeam_utils:: atomic:: AtomicCell ;
@@ -335,8 +341,87 @@ mod mmap {
335341 }
336342 }
337343
338- #[ pyimpl( with( Constructor ) , flags( BASETYPE ) ) ]
344+ static BUFFER_METHODS : BufferMethods = BufferMethods {
345+ obj_bytes : |buffer| buffer. obj_as :: < PyMmap > ( ) . as_bytes ( ) ,
346+ obj_bytes_mut : |buffer| buffer. obj_as :: < PyMmap > ( ) . as_bytes_mut ( ) ,
347+ release : |buffer| {
348+ buffer. obj_as :: < PyMmap > ( ) . exports . fetch_sub ( 1 ) ;
349+ } ,
350+ retain : |buffer| {
351+ buffer. obj_as :: < PyMmap > ( ) . exports . fetch_add ( 1 ) ;
352+ } ,
353+ } ;
354+
355+ impl AsBuffer for PyMmap {
356+ fn as_buffer ( zelf : & Py < Self > , _vm : & VirtualMachine ) -> PyResult < PyBuffer > {
357+ let buf = PyBuffer :: new (
358+ zelf. to_owned ( ) . into ( ) ,
359+ BufferDescriptor :: simple ( zelf. len ( ) , true ) ,
360+ & BUFFER_METHODS ,
361+ ) ;
362+
363+ Ok ( buf)
364+ }
365+ }
366+
367+ impl AsMapping for PyMmap {
368+ const AS_MAPPING : PyMappingMethods = PyMappingMethods {
369+ length : Some ( |mapping, _vm| Ok ( Self :: mapping_downcast ( mapping) . len ( ) ) ) ,
370+ subscript : Some ( |mapping, needle, vm| {
371+ Self :: mapping_downcast ( mapping) . _getitem ( needle, vm)
372+ } ) ,
373+ ass_subscript : Some ( |mapping, needle, value, vm| {
374+ let zelf = Self :: mapping_downcast ( mapping) ;
375+ if let Some ( value) = value {
376+ Self :: _setitem ( zelf. to_owned ( ) , needle, value, vm)
377+ } else {
378+ Err ( vm. new_type_error ( "mmap object doesn't support item deletion" . to_owned ( ) ) )
379+ }
380+ } ) ,
381+ } ;
382+ }
383+
384+ impl AsSequence for PyMmap {
385+ const AS_SEQUENCE : PySequenceMethods = PySequenceMethods {
386+ length : Some ( |seq, _vm| Ok ( Self :: sequence_downcast ( seq) . len ( ) ) ) ,
387+ item : Some ( |seq, i, vm| {
388+ let zelf = Self :: sequence_downcast ( seq) ;
389+ zelf. get_item_by_index ( i, vm)
390+ } ) ,
391+ ass_item : Some ( |seq, i, value, vm| {
392+ let zelf = Self :: sequence_downcast ( seq) ;
393+ if let Some ( value) = value {
394+ Self :: setitem_by_index ( zelf. to_owned ( ) , i, value, vm)
395+ } else {
396+ Err ( vm. new_type_error ( "mmap object doesn't support item deletion" . to_owned ( ) ) )
397+ }
398+ } ) ,
399+ ..PySequenceMethods :: NOT_IMPLEMENTED
400+ } ;
401+ }
402+
403+ #[ pyimpl( with( Constructor , AsMapping , AsSequence , AsBuffer ) , flags( BASETYPE ) ) ]
339404 impl PyMmap {
405+ fn as_bytes_mut ( & self ) -> BorrowedValueMut < [ u8 ] > {
406+ PyMutexGuard :: map ( self . mmap . lock ( ) , |m| {
407+ match m. as_mut ( ) . expect ( "mmap closed or invalid" ) {
408+ MmapObj :: Read ( _) => panic ! ( "mmap can't modify a readonly memory map." ) ,
409+ MmapObj :: Write ( mmap) => & mut mmap[ ..] ,
410+ }
411+ } )
412+ . into ( )
413+ }
414+
415+ fn as_bytes ( & self ) -> BorrowedValue < [ u8 ] > {
416+ PyMutexGuard :: map_immutable ( self . mmap . lock ( ) , |m| {
417+ match m. as_ref ( ) . expect ( "mmap closed or invalid" ) {
418+ MmapObj :: Read ( ref mmap) => & mmap[ ..] ,
419+ MmapObj :: Write ( ref mmap) => & mmap[ ..] ,
420+ }
421+ } )
422+ . into ( )
423+ }
424+
340425 #[ pymethod( magic) ]
341426 pub ( crate ) fn len ( & self ) -> usize {
342427 self . inner_size ( ) as usize
@@ -789,6 +874,155 @@ mod mmap {
789874 Ok ( ( ) )
790875 }
791876
877+ fn get_item_by_index ( & self , i : isize , vm : & VirtualMachine ) -> PyResult < PyObjectRef > {
878+ let i = wrap_index ( i, self . len ( ) )
879+ . ok_or_else ( || vm. new_index_error ( "mmap index out of range" . to_owned ( ) ) ) ?;
880+
881+ let b = match self . check_valid ( vm) ?. deref ( ) . as_ref ( ) . unwrap ( ) {
882+ MmapObj :: Read ( mmap) => mmap[ i as usize ] ,
883+ MmapObj :: Write ( mmap) => mmap[ i as usize ] ,
884+ } ;
885+
886+ Ok ( PyInt :: from ( b) . into_ref ( vm) . into ( ) )
887+ }
888+
889+ fn getitem_by_slice (
890+ & self ,
891+ slice : & SaturatedSlice ,
892+ vm : & VirtualMachine ,
893+ ) -> PyResult < PyObjectRef > {
894+ let ( range, step, slicelen) = slice. adjust_indices ( self . len ( ) ) ;
895+
896+ let mmap = self . check_valid ( vm) ?;
897+
898+ if slicelen == 0 {
899+ return Ok ( PyBytes :: from ( vec ! [ ] ) . into_ref ( vm) . into ( ) ) ;
900+ } else if step == 1 {
901+ let bytes = match mmap. deref ( ) . as_ref ( ) . unwrap ( ) {
902+ MmapObj :: Read ( mmap) => & mmap[ range] ,
903+ MmapObj :: Write ( mmap) => & mmap[ range] ,
904+ } ;
905+ return Ok ( PyBytes :: from ( bytes. to_vec ( ) ) . into_ref ( vm) . into ( ) ) ;
906+ }
907+
908+ let mut result_buf = Vec :: with_capacity ( slicelen) ;
909+ if step. is_negative ( ) {
910+ for i in range. rev ( ) . step_by ( step. unsigned_abs ( ) ) {
911+ let b = match mmap. deref ( ) . as_ref ( ) . unwrap ( ) {
912+ MmapObj :: Read ( mmap) => mmap[ i] ,
913+ MmapObj :: Write ( mmap) => mmap[ i] ,
914+ } ;
915+ result_buf. push ( b) ;
916+ }
917+ } else {
918+ for i in range. step_by ( step. unsigned_abs ( ) ) {
919+ let b = match mmap. deref ( ) . as_ref ( ) . unwrap ( ) {
920+ MmapObj :: Read ( mmap) => mmap[ i] ,
921+ MmapObj :: Write ( mmap) => mmap[ i] ,
922+ } ;
923+ result_buf. push ( b) ;
924+ }
925+ }
926+ Ok ( PyBytes :: from ( result_buf) . into_ref ( vm) . into ( ) )
927+ }
928+
929+ fn _getitem ( & self , needle : & PyObject , vm : & VirtualMachine ) -> PyResult < PyObjectRef > {
930+ match SequenceIndex :: try_from_borrowed_object ( vm, needle, "mmap" ) ? {
931+ SequenceIndex :: Int ( i) => self . get_item_by_index ( i, vm) ,
932+ SequenceIndex :: Slice ( slice) => self . getitem_by_slice ( & slice, vm) ,
933+ }
934+ }
935+
936+ #[ pymethod( magic) ]
937+ fn getitem ( & self , needle : PyObjectRef , vm : & VirtualMachine ) -> PyResult < PyObjectRef > {
938+ self . _getitem ( & needle, vm)
939+ }
940+
941+ fn _setitem (
942+ zelf : PyRef < Self > ,
943+ needle : & PyObject ,
944+ value : PyObjectRef ,
945+ vm : & VirtualMachine ,
946+ ) -> PyResult < ( ) > {
947+ match SequenceIndex :: try_from_borrowed_object ( vm, needle, "mmap" ) ? {
948+ SequenceIndex :: Int ( i) => Self :: setitem_by_index ( zelf, i, value, vm) ,
949+ SequenceIndex :: Slice ( slice) => Self :: setitem_by_slice ( zelf, & slice, value, vm) ,
950+ }
951+ }
952+
953+ fn setitem_by_index (
954+ zelf : PyRef < Self > ,
955+ i : isize ,
956+ value : PyObjectRef ,
957+ vm : & VirtualMachine ,
958+ ) -> PyResult < ( ) > {
959+ let i = wrap_index ( i, zelf. len ( ) )
960+ . ok_or_else ( || vm. new_index_error ( "mmap index out of range" . to_owned ( ) ) ) ?;
961+
962+ let b = value_from_object ( vm, & value) ?;
963+
964+ zelf. try_writable ( vm, |mmap| {
965+ mmap[ i as usize ] = b;
966+ } ) ?;
967+
968+ Ok ( ( ) )
969+ }
970+
971+ fn setitem_by_slice (
972+ zelf : PyRef < Self > ,
973+ slice : & SaturatedSlice ,
974+ value : PyObjectRef ,
975+ vm : & VirtualMachine ,
976+ ) -> PyResult < ( ) > {
977+ let ( range, step, slicelen) = slice. adjust_indices ( zelf. len ( ) ) ;
978+
979+ let bytes = bytes_from_object ( vm, & value) ?;
980+
981+ if bytes. len ( ) != slicelen {
982+ return Err ( vm. new_index_error ( "mmap slice assignment is wrong size" . to_owned ( ) ) ) ;
983+ }
984+
985+ if slicelen == 0 {
986+ // do nothing
987+ Ok ( ( ) )
988+ } else if step == 1 {
989+ zelf. try_writable ( vm, |mmap| {
990+ ( & mut mmap[ range] )
991+ . write ( & bytes)
992+ . map_err ( |e| vm. new_os_error ( e. to_string ( ) ) ) ?;
993+ Ok ( ( ) )
994+ } ) ?
995+ } else {
996+ let mut bi = 0 ; // bytes index
997+ if step. is_negative ( ) {
998+ for i in range. rev ( ) . step_by ( step. unsigned_abs ( ) ) {
999+ zelf. try_writable ( vm, |mmap| {
1000+ mmap[ i] = bytes[ bi] ;
1001+ } ) ?;
1002+ bi += 1 ;
1003+ }
1004+ } else {
1005+ for i in range. step_by ( step. unsigned_abs ( ) ) {
1006+ zelf. try_writable ( vm, |mmap| {
1007+ mmap[ i] = bytes[ bi] ;
1008+ } ) ?;
1009+ bi += 1 ;
1010+ }
1011+ }
1012+ Ok ( ( ) )
1013+ }
1014+ }
1015+
1016+ #[ pymethod( magic) ]
1017+ fn setitem (
1018+ zelf : PyRef < Self > ,
1019+ needle : PyObjectRef ,
1020+ value : PyObjectRef ,
1021+ vm : & VirtualMachine ,
1022+ ) -> PyResult < ( ) > {
1023+ Self :: _setitem ( zelf, & needle, value, vm)
1024+ }
1025+
7921026 #[ pymethod( magic) ]
7931027 fn enter ( zelf : PyRef < Self > , vm : & VirtualMachine ) -> PyResult < PyRef < Self > > {
7941028 let _m = zelf. check_valid ( vm) ?;
0 commit comments