@@ -18,7 +18,7 @@ use std::path::PathBuf;
1818
1919pub ( crate ) trait AsBytes {
2020 fn as_bytes ( & self ) -> & [ u8 ] ;
21- fn as_bytes_mut ( & mut self ) -> & mut [ u8 ] ;
21+ fn as_bytes_mut ( & mut self ) -> PyResult < & mut [ u8 ] > ;
2222}
2323
2424/// A native Rust file-like object. Reading and writing takes place
@@ -49,7 +49,7 @@ impl AsBytes for RustyFile {
4949 entire file into memory; consider using cramjam.Buffer"
5050 )
5151 }
52- fn as_bytes_mut ( & mut self ) -> & mut [ u8 ] {
52+ fn as_bytes_mut ( & mut self ) -> PyResult < & mut [ u8 ] > {
5353 unimplemented ! (
5454 "Converting a File to bytes is not supported, as it'd require reading the \
5555 entire file into memory; consider using cramjam.Buffer"
@@ -194,21 +194,24 @@ impl PythonBuffer {
194194 }
195195 /// Is the Python buffer readonly
196196 pub fn readonly ( & self ) -> bool {
197- self . inner . readonly != 0
197+ self . inner . readonly == 1
198198 }
199199 /// Get the underlying buffer as a slice of bytes
200200 pub fn as_slice ( & self ) -> & [ u8 ] {
201201 unsafe { std:: slice:: from_raw_parts ( self . buf_ptr ( ) as * const u8 , self . len_bytes ( ) ) }
202202 }
203203 /// Get the underlying buffer as a mutable slice of bytes
204204 pub fn as_slice_mut ( & mut self ) -> PyResult < & mut [ u8 ] > {
205- // TODO: For v3 release, add self.readonly check; bytes is readonly but
206- // v1 and v2 releases have not treated it as such.
205+ if self . readonly ( ) {
206+ let repr = Python :: with_gil ( |py| unsafe { PyObject :: from_borrowed_ptr ( py, self . inner . obj ) } . to_string ( ) ) ;
207+ let msg = format ! ( "The output buffer '{}' is readonly, refusing to overwrite." , repr) ;
208+ return Err ( pyo3:: exceptions:: PyTypeError :: new_err ( msg) ) ;
209+ }
207210 Ok ( unsafe { std:: slice:: from_raw_parts_mut ( self . buf_ptr ( ) as * mut u8 , self . len_bytes ( ) ) } )
208211 }
209212 /// If underlying buffer is c_contiguous
210213 pub fn is_c_contiguous ( & self ) -> bool {
211- unsafe { ffi:: PyBuffer_IsContiguous ( & * self . inner as * const ffi:: Py_buffer , b'C' as std:: os:: raw:: c_char ) != 0 }
214+ unsafe { ffi:: PyBuffer_IsContiguous ( & * self . inner as * const ffi:: Py_buffer , b'C' as std:: os:: raw:: c_char ) == 1 }
212215 }
213216 /// Dimensions for buffer
214217 pub fn dimensions ( & self ) -> usize {
@@ -244,46 +247,17 @@ impl<'py> FromPyObject<'py> for PythonBuffer {
244247 }
245248}
246249
247- #[ cfg( not( PyPy ) ) ]
248- fn make_py_buffer ( obj : & PyAny ) -> PyResult < ffi:: Py_buffer > {
249- let mut buf = mem:: MaybeUninit :: uninit ( ) ;
250- let rc = unsafe { ffi:: PyObject_GetBuffer ( obj. as_ptr ( ) , buf. as_mut_ptr ( ) , ffi:: PyBUF_CONTIG_RO ) } ;
251- if rc != 0 {
252- return Err ( exceptions:: PyBufferError :: new_err (
253- "Failed to get buffer, is it C contiguous, and shape is not null?" ,
254- ) ) ;
255- }
256- let buf = unsafe { mem:: MaybeUninit :: < ffi:: Py_buffer > :: assume_init ( buf) } ;
257- Ok ( buf)
258- }
259-
260- #[ cfg( PyPy ) ]
261- fn make_py_buffer ( obj : & PyAny ) -> PyResult < ffi:: Py_buffer > {
262- let is_memview = unsafe { ffi:: PyMemoryView_Check ( obj. as_ptr ( ) ) } == 1 ;
263-
264- let mut object = Python :: with_gil ( |py| obj. to_object ( py) ) ;
265-
266- if !is_memview {
267- let ptr = unsafe { ffi:: PyMemoryView_FromObject ( obj. as_ptr ( ) ) } ;
268- Python :: with_gil ( |py| {
269- object = unsafe { PyObject :: from_owned_ptr ( py, ptr) } ;
270- } )
271- }
272- let mut buf = mem:: MaybeUninit :: uninit ( ) ;
273- let rc = unsafe { ffi:: PyObject_GetBuffer ( object. as_ptr ( ) , buf. as_mut_ptr ( ) , ffi:: PyBUF_CONTIG_RO ) } ;
274- if rc != 0 {
275- return Err ( exceptions:: PyBufferError :: new_err (
276- "Failed to get buffer, is it C contiguous, and shape is not null?" ,
277- ) ) ;
278- }
279- let buf = unsafe { mem:: MaybeUninit :: < ffi:: Py_buffer > :: assume_init ( buf) } ;
280- Ok ( buf)
281- }
282-
283250impl < ' py > TryFrom < & ' py PyAny > for PythonBuffer {
284251 type Error = PyErr ;
285252 fn try_from ( obj : & ' py PyAny ) -> Result < Self , Self :: Error > {
286- let py_buffer = make_py_buffer ( obj) ?;
253+ let mut buf = mem:: MaybeUninit :: uninit ( ) ;
254+ let rc = unsafe { ffi:: PyObject_GetBuffer ( obj. as_ptr ( ) , buf. as_mut_ptr ( ) , ffi:: PyBUF_CONTIG_RO ) } ;
255+ if rc != 0 {
256+ return Err ( exceptions:: PyBufferError :: new_err (
257+ "Failed to get buffer, is it C contiguous, and shape is not null?" ,
258+ ) ) ;
259+ }
260+ let py_buffer = unsafe { mem:: MaybeUninit :: < ffi:: Py_buffer > :: assume_init ( buf) } ;
287261 let buf = Self {
288262 inner : std:: pin:: Pin :: from ( Box :: new ( py_buffer) ) ,
289263 pos : 0 ,
@@ -357,8 +331,9 @@ impl AsBytes for RustyBuffer {
357331 fn as_bytes ( & self ) -> & [ u8 ] {
358332 self . inner . get_ref ( ) . as_slice ( )
359333 }
360- fn as_bytes_mut ( & mut self ) -> & mut [ u8 ] {
361- self . inner . get_mut ( ) . as_mut_slice ( )
334+ fn as_bytes_mut ( & mut self ) -> PyResult < & mut [ u8 ] > {
335+ let slice = self . inner . get_mut ( ) . as_mut_slice ( ) ;
336+ Ok ( slice)
362337 }
363338}
364339
0 commit comments