Skip to content

Commit 51e0988

Browse files
committed
Trying doing things the right way, CPython happy, PyPy sad [skip ci]
1 parent a477ed3 commit 51e0988

File tree

4 files changed

+32
-57
lines changed

4 files changed

+32
-57
lines changed

cramjam-python/src/io.rs

Lines changed: 20 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use std::path::PathBuf;
1818

1919
pub(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-
283250
impl<'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

cramjam-python/src/lib.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -101,18 +101,18 @@ impl<'a> AsBytes for BytesType<'a> {
101101
}
102102
}
103103
}
104-
fn as_bytes_mut(&mut self) -> &mut [u8] {
104+
fn as_bytes_mut(&mut self) -> PyResult<&mut [u8]> {
105105
match self {
106106
BytesType::RustyBuffer(b) => {
107107
let mut py_ref = b.borrow_mut();
108-
let bytes = py_ref.as_bytes_mut();
109-
unsafe { std::slice::from_raw_parts_mut(bytes.as_mut_ptr(), bytes.len()) }
108+
let bytes = py_ref.as_bytes_mut()?;
109+
Ok(unsafe { std::slice::from_raw_parts_mut(bytes.as_mut_ptr(), bytes.len()) })
110110
}
111-
BytesType::PyBuffer(b) => b.as_slice_mut().unwrap(),
111+
BytesType::PyBuffer(b) => b.as_slice_mut(),
112112
BytesType::RustyFile(b) => {
113113
let mut py_ref = b.borrow_mut();
114-
let bytes = py_ref.as_bytes_mut();
115-
unsafe { std::slice::from_raw_parts_mut(bytes.as_mut_ptr(), bytes.len()) }
114+
let bytes = py_ref.as_bytes_mut()?;
115+
Ok(unsafe { std::slice::from_raw_parts_mut(bytes.as_mut_ptr(), bytes.len()) })
116116
}
117117
}
118118
}
@@ -212,7 +212,7 @@ macro_rules! generic {
212212
})
213213
},
214214
_ => {
215-
let bytes_out = $output.as_bytes_mut();
215+
let bytes_out = $output.as_bytes_mut()?;
216216
$py.allow_threads(|| {
217217
$op(f_in, &mut Cursor::new(bytes_out) $(, $level)? )
218218
})
@@ -237,7 +237,7 @@ macro_rules! generic {
237237
})
238238
},
239239
_ => {
240-
let bytes_out = $output.as_bytes_mut();
240+
let bytes_out = $output.as_bytes_mut()?;
241241
$py.allow_threads(|| {
242242
$op(bytes_in, &mut Cursor::new(bytes_out) $(, $level)?)
243243
})

cramjam-python/src/lz4.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ pub fn compress_block(
146146
#[pyfunction]
147147
pub fn decompress_block_into(py: Python, input: BytesType, mut output: BytesType) -> PyResult<usize> {
148148
let bytes = input.as_bytes();
149-
let out_bytes = output.as_bytes_mut();
149+
let out_bytes = output.as_bytes_mut()?;
150150
py.allow_threads(|| libcramjam::lz4::block::decompress_into(bytes, out_bytes, Some(true)))
151151
.map_err(DecompressionError::from_err)
152152
.map(|v| v as _)
@@ -180,7 +180,7 @@ pub fn compress_block_into(
180180
store_size: Option<bool>,
181181
) -> PyResult<usize> {
182182
let bytes = data.as_bytes();
183-
let out_bytes = output.as_bytes_mut();
183+
let out_bytes = output.as_bytes_mut()?;
184184
py.allow_threads(|| {
185185
libcramjam::lz4::block::compress_into(bytes, out_bytes, compression.map(|v| v as _), acceleration, store_size)
186186
})

cramjam-python/src/snappy.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ pub fn decompress_into(py: Python, input: BytesType, mut output: BytesType) -> P
100100
#[pyfunction]
101101
pub fn compress_raw_into(py: Python, input: BytesType, mut output: BytesType) -> PyResult<usize> {
102102
let bytes_in = input.as_bytes();
103-
let bytes_out = output.as_bytes_mut();
103+
let bytes_out = output.as_bytes_mut()?;
104104
py.allow_threads(|| libcramjam::snappy::raw::compress(bytes_in, bytes_out))
105105
.map_err(CompressionError::from_err)
106106
}
@@ -109,7 +109,7 @@ pub fn compress_raw_into(py: Python, input: BytesType, mut output: BytesType) ->
109109
#[pyfunction]
110110
pub fn decompress_raw_into(py: Python, input: BytesType, mut output: BytesType) -> PyResult<usize> {
111111
let bytes_in = input.as_bytes();
112-
let bytes_out = output.as_bytes_mut();
112+
let bytes_out = output.as_bytes_mut()?;
113113
py.allow_threads(|| libcramjam::snappy::raw::decompress(bytes_in, bytes_out))
114114
.map_err(DecompressionError::from_err)
115115
}

0 commit comments

Comments
 (0)