# pyo3-bytes

Integration between [`bytes`](https://docs.rs/bytes) and [`pyo3`](https://github.com/PyO3/pyo3).

This provides [`PyBytes`], a wrapper around [`Bytes`][::bytes::Bytes] that supports the [Python buffer protocol](https://docs.python.org/3/c-api/buffer.html).

This uses the new [`Bytes::from_owner` API](https://docs.rs/bytes/latest/bytes/struct.Bytes.html#method.from_owner) introduced in `bytes` 1.9.

Since this integration uses the Python buffer protocol, any library that uses `pyo3-bytes` must set the feature flags for the `pyo3` dependency correctly. `pyo3` must either _not_ have an [`abi3` feature flag](https://pyo3.rs/v0.23.4/features.html#abi3) (in which case maturin will generate wheels per Python version), or have `abi3-py311` (which supports only Python 3.11+), since the buffer protocol became part of the Python stable ABI [as of Python 3.11](https://docs.python.org/3/c-api/buffer.html#c.Py_buffer).

## Importing buffers to Rust

Just use `PyBytes` as a type in your functions or methods exposed to Python.

```rs
use pyo3_bytes::PyBytes;
use bytes::Bytes;

#[pyfunction]
pub fn use_bytes(buffer: PyBytes) {
    let buffer: Bytes = buffer.into_inner();
}
```

## Exporting buffers to Python

Return the `PyBytes` class from your function.

```rs
use pyo3_bytes::PyBytes;
use bytes::Bytes;

#[pyfunction]
pub fn return_bytes() -> PyBytes {
    let buffer = Bytes::from_static(b"hello");
    PyBytes::new(buffer)
}
```

## Safety

Unfortunately, this interface cannot be 100% safe, as the Python buffer protocol does not enforce buffer immutability.

The Python user must take care to not mutate the buffers that have been passed
to Rust.

For more reading:

- <https://alexgaynor.net/2022/oct/23/buffers-on-the-edge/>
- <https://github.com/PyO3/pyo3/issues/2824>
- <https://github.com/PyO3/pyo3/issues/4736>

## Python type hints

On the Python side, the exported `Bytes` class implements many of the same
methods (with the same signature) as the Python `bytes` object.

The Python type hints are available in the Github repo in the file `bytes.pyi`.
I don't know the best way to distribute this to downstream projects. If you have
an idea, create an issue to discuss.

## Version compatibility

| pyo3-bytes | pyo3 |
| ---------- | ---- |
| 0.1.x      | 0.23 |
| 0.2.x      | 0.24 |
| 0.3.x      | 0.25 |
| 0.4.x      | 0.26 |
| 0.5.x      | 0.27 |
| 0.6.x      | 0.28 |
