@@ -18,14 +18,18 @@ mod _io {
18
18
use std:: io:: { self , prelude:: * , Cursor , SeekFrom } ;
19
19
20
20
use crate :: byteslike:: { PyBytesLike , PyRwBytesLike } ;
21
- use crate :: common:: cell:: { PyRwLock , PyRwLockWriteGuard } ;
21
+ use crate :: common:: borrow:: { BorrowedValue , BorrowedValueMut } ;
22
+ use crate :: common:: cell:: {
23
+ PyRwLock , PyRwLockReadGuard , PyRwLockUpgradableReadGuard , PyRwLockWriteGuard ,
24
+ } ;
22
25
use crate :: exceptions:: { IntoPyException , PyBaseExceptionRef } ;
23
26
use crate :: function:: { Args , KwArgs , OptionalArg , OptionalOption , PyFuncArgs } ;
24
27
use crate :: obj:: objbool;
25
28
use crate :: obj:: objbytearray:: PyByteArray ;
26
29
use crate :: obj:: objbytes:: PyBytesRef ;
27
30
use crate :: obj:: objint;
28
31
use crate :: obj:: objiter;
32
+ use crate :: obj:: objmemory:: { Buffer , BufferOptions , BufferRef , PyMemoryView , PyMemoryViewRef } ;
29
33
use crate :: obj:: objstr:: { self , PyStr , PyStrRef } ;
30
34
use crate :: obj:: objtype:: { self , PyTypeRef } ;
31
35
use crate :: pyobject:: {
@@ -939,6 +943,8 @@ mod _io {
939
943
struct BytesIO {
940
944
buffer : PyRwLock < BufferedIO > ,
941
945
closed : AtomicCell < bool > ,
946
+ exports : AtomicCell < usize > ,
947
+ buffer_options : PyRwLock < Option < Box < BufferOptions > > > ,
942
948
}
943
949
944
950
type BytesIORef = PyRef < BytesIO > ;
@@ -972,6 +978,8 @@ mod _io {
972
978
BytesIO {
973
979
buffer : PyRwLock :: new ( BufferedIO :: new ( Cursor :: new ( raw_bytes) ) ) ,
974
980
closed : AtomicCell :: new ( false ) ,
981
+ exports : AtomicCell :: new ( 0 ) ,
982
+ buffer_options : PyRwLock :: new ( None ) ,
975
983
}
976
984
. into_ref_with_type ( vm, cls)
977
985
}
@@ -981,6 +989,7 @@ mod _io {
981
989
impl BytesIORef {
982
990
#[ pymethod]
983
991
fn write ( self , data : PyBytesLike , vm : & VirtualMachine ) -> PyResult < u64 > {
992
+ self . try_resizable ( vm) ?;
984
993
let mut buffer = self . buffer ( vm) ?;
985
994
match data. with_ref ( |b| buffer. write ( b) ) {
986
995
Some ( value) => Ok ( value) ,
@@ -1048,6 +1057,7 @@ mod _io {
1048
1057
1049
1058
#[ pymethod]
1050
1059
fn truncate ( self , pos : OptionalSize , vm : & VirtualMachine ) -> PyResult < ( ) > {
1060
+ self . try_resizable ( vm) ?;
1051
1061
let mut buffer = self . buffer ( vm) ?;
1052
1062
buffer. truncate ( pos. try_usize ( vm) ?) ?;
1053
1063
Ok ( ( ) )
@@ -1059,8 +1069,57 @@ mod _io {
1059
1069
}
1060
1070
1061
1071
#[ 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
1064
1123
}
1065
1124
}
1066
1125
0 commit comments