@@ -18,14 +18,18 @@ mod _io {
1818 use std:: io:: { self , prelude:: * , Cursor , SeekFrom } ;
1919
2020 use crate :: byteslike:: { PyBytesLike , PyRwBytesLike } ;
21- use crate :: common:: lock:: { PyRwLock , PyRwLockWriteGuard } ;
21+ use crate :: common:: borrow:: { BorrowedValue , BorrowedValueMut } ;
22+ use crate :: common:: lock:: {
23+ PyRwLock , PyRwLockReadGuard , PyRwLockUpgradableReadGuard , PyRwLockWriteGuard ,
24+ } ;
2225 use crate :: exceptions:: { IntoPyException , PyBaseExceptionRef } ;
2326 use crate :: function:: { Args , KwArgs , OptionalArg , OptionalOption , PyFuncArgs } ;
2427 use crate :: obj:: objbool;
2528 use crate :: obj:: objbytearray:: PyByteArray ;
2629 use crate :: obj:: objbytes:: PyBytesRef ;
2730 use crate :: obj:: objint;
2831 use crate :: obj:: objiter;
32+ use crate :: obj:: objmemory:: { Buffer , BufferOptions , BufferRef , PyMemoryView , PyMemoryViewRef } ;
2933 use crate :: obj:: objstr:: { self , PyStr , PyStrRef } ;
3034 use crate :: obj:: objtype:: { self , PyTypeRef } ;
3135 use crate :: pyobject:: {
@@ -939,6 +943,8 @@ mod _io {
939943 struct BytesIO {
940944 buffer : PyRwLock < BufferedIO > ,
941945 closed : AtomicCell < bool > ,
946+ exports : AtomicCell < usize > ,
947+ buffer_options : PyRwLock < Option < Box < BufferOptions > > > ,
942948 }
943949
944950 type BytesIORef = PyRef < BytesIO > ;
@@ -972,6 +978,8 @@ mod _io {
972978 BytesIO {
973979 buffer : PyRwLock :: new ( BufferedIO :: new ( Cursor :: new ( raw_bytes) ) ) ,
974980 closed : AtomicCell :: new ( false ) ,
981+ exports : AtomicCell :: new ( 0 ) ,
982+ buffer_options : PyRwLock :: new ( None ) ,
975983 }
976984 . into_ref_with_type ( vm, cls)
977985 }
@@ -981,6 +989,7 @@ mod _io {
981989 impl BytesIORef {
982990 #[ pymethod]
983991 fn write ( self , data : PyBytesLike , vm : & VirtualMachine ) -> PyResult < u64 > {
992+ self . try_resizable ( vm) ?;
984993 let mut buffer = self . buffer ( vm) ?;
985994 match data. with_ref ( |b| buffer. write ( b) ) {
986995 Some ( value) => Ok ( value) ,
@@ -1048,6 +1057,7 @@ mod _io {
10481057
10491058 #[ pymethod]
10501059 fn truncate ( self , pos : OptionalSize , vm : & VirtualMachine ) -> PyResult < ( ) > {
1060+ self . try_resizable ( vm) ?;
10511061 let mut buffer = self . buffer ( vm) ?;
10521062 buffer. truncate ( pos. try_usize ( vm) ?) ?;
10531063 Ok ( ( ) )
@@ -1059,8 +1069,57 @@ mod _io {
10591069 }
10601070
10611071 #[ pymethod]
1062- fn close ( self ) {
1063- self . closed . store ( true )
1072+ fn close ( self , vm : & VirtualMachine ) -> PyResult < ( ) > {
1073+ self . try_resizable ( vm) ?;
1074+ self . closed . store ( true ) ;
1075+ Ok ( ( ) )
1076+ }
1077+
1078+ #[ pymethod]
1079+ fn getbuffer ( self , vm : & VirtualMachine ) -> PyResult < PyMemoryViewRef > {
1080+ let buffer: Box < dyn Buffer > = Box :: new ( self . clone ( ) ) ;
1081+ let buffer = BufferRef :: from ( buffer) ;
1082+ let view = PyMemoryView :: from_buffer ( self . clone ( ) . into_object ( ) , buffer, vm) ?;
1083+ self . exports . fetch_add ( 1 ) ;
1084+ Ok ( view. into_ref ( vm) )
1085+ }
1086+ }
1087+
1088+ impl Buffer for BytesIORef {
1089+ fn get_options ( & self ) -> BorrowedValue < BufferOptions > {
1090+ let guard = self . buffer_options . upgradable_read ( ) ;
1091+ let guard = if guard. is_none ( ) {
1092+ let mut w = PyRwLockUpgradableReadGuard :: upgrade ( guard) ;
1093+ * w = Some ( Box :: new ( BufferOptions {
1094+ readonly : false ,
1095+ len : self . buffer . read ( ) . cursor . get_ref ( ) . len ( ) ,
1096+ ..Default :: default ( )
1097+ } ) ) ;
1098+ PyRwLockWriteGuard :: downgrade ( w)
1099+ } else {
1100+ PyRwLockUpgradableReadGuard :: downgrade ( guard)
1101+ } ;
1102+ PyRwLockReadGuard :: map ( guard, |x| x. as_ref ( ) . unwrap ( ) . as_ref ( ) ) . into ( )
1103+ }
1104+
1105+ fn obj_bytes ( & self ) -> BorrowedValue < [ u8 ] > {
1106+ PyRwLockReadGuard :: map ( self . buffer . read ( ) , |x| x. cursor . get_ref ( ) . as_slice ( ) ) . into ( )
1107+ }
1108+
1109+ fn obj_bytes_mut ( & self ) -> BorrowedValueMut < [ u8 ] > {
1110+ PyRwLockWriteGuard :: map ( self . buffer . write ( ) , |x| x. cursor . get_mut ( ) . as_mut_slice ( ) )
1111+ . into ( )
1112+ }
1113+
1114+ fn release ( & self ) {
1115+ let mut w = self . buffer_options . write ( ) ;
1116+ if self . exports . fetch_sub ( 1 ) == 1 {
1117+ * w = None ;
1118+ }
1119+ }
1120+
1121+ fn is_resizable ( & self ) -> bool {
1122+ self . exports . load ( ) == 0
10641123 }
10651124 }
10661125
0 commit comments