Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Added Rust initialisation of Python-allocated bytes #1074

Merged
merged 8 commits into from
Aug 3, 2020
26 changes: 26 additions & 0 deletions src/types/bytes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,21 @@ impl PyBytes {
unsafe { py.from_owned_ptr(ffi::PyBytes_FromStringAndSize(ptr, len)) }
}

/// Creates a new Python bytestring object.
/// The uninitialised bytestring must be initialised in the `init` closure.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe specifically say the entire uninitialised bytestring?

Also, if you're up for it, adding a little example would be very much appreciated.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where and in what format should I add an example?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've added examples in 533c105

///
/// Panics if out of memory.
pub fn new_with<F: Fn(&mut [u8])>(py: Python<'_>, len: usize, init: F) -> &PyBytes {
juntyr marked this conversation as resolved.
Show resolved Hide resolved
let length = len as ffi::Py_ssize_t;
let pyptr = unsafe { ffi::PyBytes_FromStringAndSize(std::ptr::null(), length) };
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As this and the next 4 lines all contain unsafe, could perhaps just refactor to be a single unsafe block?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 20d27ff

// Iff pyptr is null, py.from_owned_ptr(pyptr) will panic
let pybytes = unsafe { py.from_owned_ptr(pyptr) };
let buffer = unsafe { ffi::PyBytes_AsString(pyptr) } as *mut u8;
debug_assert!(!buffer.is_null());
init(unsafe { std::slice::from_raw_parts_mut(buffer, len) });
pybytes
}

/// Creates a new Python byte string object from a raw pointer and length.
///
/// Panics if out of memory.
Expand Down Expand Up @@ -91,4 +106,15 @@ mod test {
let bytes = PyBytes::new(py, b"Hello World");
assert_eq!(bytes[1], b'e');
}

#[test]
fn test_bytes_new_with() {
let gil = Python::acquire_gil();
let py = gil.python();
let py_bytes = PyBytes::new_with(py, 10, |b: &mut [u8]| {
b.copy_from_slice(b"Hello Rust");
});
let bytes: &[u8] = FromPyObject::extract(py_bytes).unwrap();
assert_eq!(bytes, b"Hello Rust");
}
}