Replace unsound PyByteArray::data with PyByteArray::to_vec
This commit is contained in:
parent
cf8f63cacf
commit
bd86b6750e
|
@ -21,6 +21,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
|||
### Changed
|
||||
|
||||
* Implementing the Using the `gc` parameter for `pyclass` (e.g. `#[pyclass(gc)]`) without implementing the `class::PyGCProtocol` trait is now a compile-time error. Failing to implement this trait could lead to segfaults. [#532](https://github.com/PyO3/pyo3/pull/532)
|
||||
* `PyByteArray::data` has been replaced with `PyDataArray::to_vec` because returning a `&[u8]` is unsound. (See [this comment](https://github.com/PyO3/pyo3/issues/373#issuecomment-512332696) for a great write-up for why that was unsound)
|
||||
|
||||
## [0.7.0] - 2018-05-26
|
||||
|
||||
|
|
|
@ -18,8 +18,6 @@ pyobject_native_type!(PyByteArray, ffi::PyByteArray_Type, ffi::PyByteArray_Check
|
|||
impl PyByteArray {
|
||||
/// Creates a new Python bytearray object.
|
||||
/// The byte string is initialized by copying the data from the `&[u8]`.
|
||||
///
|
||||
/// Panics if out of memory.
|
||||
pub fn new<'p>(py: Python<'p>, src: &[u8]) -> &'p PyByteArray {
|
||||
let ptr = src.as_ptr() as *const c_char;
|
||||
let len = src.len() as ffi::Py_ssize_t;
|
||||
|
@ -47,16 +45,37 @@ impl PyByteArray {
|
|||
self.len() == 0
|
||||
}
|
||||
|
||||
/// Gets the Python bytearray data as byte slice.
|
||||
pub fn data(&self) -> &[u8] {
|
||||
unsafe {
|
||||
/// Copies the contents of the bytearray to a rust vector
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// # use pyo3::prelude::*;
|
||||
/// # use pyo3::types::PyByteArray;
|
||||
/// # use pyo3::types::IntoPyDict;
|
||||
/// # let gil = GILGuard::acquire();
|
||||
/// # let py = gil.python();
|
||||
/// #
|
||||
/// let bytearray = PyByteArray::new(py, b"Hello World.");
|
||||
/// let mut copied_message = bytearray.data();
|
||||
/// assert_eq!(b"Hello World.", copied_message.as_slice());
|
||||
///
|
||||
/// copied_message[11] = b'!';
|
||||
/// assert_eq!(b"Hello World!", copied_message.as_slice());
|
||||
///
|
||||
/// let locals = [("bytearray", bytearray)].into_py_dict(py);
|
||||
/// py.run("assert bytearray == b'Hello World.'", None, Some(locals)).unwrap();
|
||||
/// ```
|
||||
pub fn to_vec(&self) -> Vec<u8> {
|
||||
let slice = unsafe {
|
||||
let buffer = ffi::PyByteArray_AsString(self.0.as_ptr()) as *mut u8;
|
||||
let length = ffi::PyByteArray_Size(self.0.as_ptr()) as usize;
|
||||
slice::from_raw_parts_mut(buffer, length)
|
||||
}
|
||||
};
|
||||
slice.to_vec()
|
||||
}
|
||||
|
||||
/// Resize bytearray object.
|
||||
/// Resize bytearray object to `len`.
|
||||
pub fn resize(&self, len: usize) -> PyResult<()> {
|
||||
unsafe {
|
||||
let result = ffi::PyByteArray_Resize(self.0.as_ptr(), len as ffi::Py_ssize_t);
|
||||
|
@ -84,13 +103,13 @@ mod test {
|
|||
let src = b"Hello Python";
|
||||
let bytearray = PyByteArray::new(py, src);
|
||||
assert_eq!(src.len(), bytearray.len());
|
||||
assert_eq!(src, bytearray.data());
|
||||
assert_eq!(src, bytearray.data().as_slice());
|
||||
|
||||
let ba: PyObject = bytearray.into();
|
||||
let bytearray = PyByteArray::from(py, &ba).unwrap();
|
||||
|
||||
assert_eq!(src.len(), bytearray.len());
|
||||
assert_eq!(src, bytearray.data());
|
||||
assert_eq!(src, bytearray.data().as_slice());
|
||||
|
||||
bytearray.resize(20).unwrap();
|
||||
assert_eq!(20, bytearray.len());
|
||||
|
|
Loading…
Reference in New Issue