Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

[WIP] Efficient movement of Vec<u8> to PyBytes #1427

Closed
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 26 additions & 4 deletions src/types/bytes.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
use crate::{
ffi, AsPyPointer, FromPyObject, IntoPy, Py, PyAny, PyObject, PyResult, PyTryFrom, Python,
ToPyObject,
};
use crate::{ffi, AsPyPointer, FromPyObject, IntoPy, Py, PyAny, PyObject, PyResult, PyTryFrom, Python, ToPyObject, PyErr};
use std::ops::Index;
use std::os::raw::c_char;
use std::slice::SliceIndex;
Expand Down Expand Up @@ -64,6 +61,31 @@ impl PyBytes {
}
}

pub fn new_with_resize<F>(py: Python, len: usize, init: F) -> PyResult<&PyBytes>
where
F: FnOnce(&mut [u8]) -> PyResult<usize>,
{
unsafe {
let pyptr = ffi::PyBytes_FromStringAndSize(std::ptr::null(), len as ffi::Py_ssize_t);
// Check for an allocation error and return it
let pypybytes: Py<PyBytes> = Py::from_owned_ptr_or_err(py, pyptr)?;
let buffer = ffi::PyBytes_AsString(pyptr) as *mut u8;
debug_assert!(!buffer.is_null());
// Zero-initialise the uninitialised bytestring
std::ptr::write_bytes(buffer, 0u8, len);
// (Further) Initialise the bytestring in init
// If init returns an Err, pypybytearray will automatically deallocate the buffer
let resize = init(std::slice::from_raw_parts_mut(buffer, len)).unwrap();
let result = ffi::_PyBytes_Resize(&mut pypybytes.as_ptr(), resize as ffi::Py_ssize_t);
if result == 0 {
Ok(pypybytes.into_ref(py))
} else {
Err(PyErr::fetch(py))
}

}
}

/// Creates a new Python byte string object from a raw pointer and length.
///
/// Panics if out of memory.
Expand Down