Added an as_bytes method for Py<PyBytes>
This allows for obtaining a slice that's not lexically bound to the GIL which can be helpful to avoid copying.
This commit is contained in:
parent
16ad15e04f
commit
69655454c1
|
@ -14,6 +14,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
|
|
||||||
- Panic during compilation when `PYO3_CROSS_LIB_DIR` is set for some host/target combinations. [#2232](https://github.com/PyO3/pyo3/pull/2232)
|
- Panic during compilation when `PYO3_CROSS_LIB_DIR` is set for some host/target combinations. [#2232](https://github.com/PyO3/pyo3/pull/2232)
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Added `as_bytes` on `Py<PyBytes>`. [#2235](https://github.com/PyO3/pyo3/pull/2235)
|
||||||
|
|
||||||
## [0.16.2] - 2022-03-15
|
## [0.16.2] - 2022-03-15
|
||||||
|
|
||||||
### Packaging
|
### Packaging
|
||||||
|
|
|
@ -97,6 +97,24 @@ impl PyBytes {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Py<PyBytes> {
|
||||||
|
/// Gets the Python bytes as a byte slice. Because Python bytes are
|
||||||
|
/// immutable, the result may be used for as long as the reference to
|
||||||
|
/// `self` is held, including when the GIL is released.
|
||||||
|
pub fn as_bytes<'a>(&'a self, _py: Python<'_>) -> &'a [u8] {
|
||||||
|
// py is required here because `PyBytes_AsString` and `PyBytes_Size`
|
||||||
|
// can both technically raise exceptions which require the GIL to be
|
||||||
|
// held. The only circumstance in which they raise is if the value
|
||||||
|
// isn't really a `PyBytes`, but better safe than sorry.
|
||||||
|
unsafe {
|
||||||
|
let buffer = ffi::PyBytes_AsString(self.as_ptr()) as *const u8;
|
||||||
|
let length = ffi::PyBytes_Size(self.as_ptr()) as usize;
|
||||||
|
debug_assert!(!buffer.is_null());
|
||||||
|
std::slice::from_raw_parts(buffer, length)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// This is the same way [Vec] is indexed.
|
/// This is the same way [Vec] is indexed.
|
||||||
impl<I: SliceIndex<[u8]>> Index<I> for PyBytes {
|
impl<I: SliceIndex<[u8]>> Index<I> for PyBytes {
|
||||||
type Output = I::Output;
|
type Output = I::Output;
|
||||||
|
|
|
@ -41,3 +41,18 @@ fn test_bytearray_vec_conversion() {
|
||||||
let f = wrap_pyfunction!(bytes_vec_conversion)(py).unwrap();
|
let f = wrap_pyfunction!(bytes_vec_conversion)(py).unwrap();
|
||||||
py_assert!(py, f, "f(bytearray(b'Hello World')) == b'Hello World'");
|
py_assert!(py, f, "f(bytearray(b'Hello World')) == b'Hello World'");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_py_as_bytes() {
|
||||||
|
let pyobj: pyo3::Py<pyo3::types::PyBytes>;
|
||||||
|
let data: &[u8];
|
||||||
|
|
||||||
|
{
|
||||||
|
let gil = Python::acquire_gil();
|
||||||
|
let py = gil.python();
|
||||||
|
pyobj = pyo3::types::PyBytes::new(py, b"abc").into_py(py);
|
||||||
|
data = pyobj.as_bytes(py);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_eq!(data, b"abc");
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue