https://github.com/althonos/iocursor
A zero-copy file-like wrapper for Python byte buffers, inspired by Rust's std::io::Cursor.
https://github.com/althonos/iocursor
buffer file-like python python-c-extension python-extension sans-io zero-copy
Last synced: 6 months ago
JSON representation
A zero-copy file-like wrapper for Python byte buffers, inspired by Rust's std::io::Cursor.
- Host: GitHub
- URL: https://github.com/althonos/iocursor
- Owner: althonos
- License: mit
- Created: 2021-02-03T18:18:31.000Z (over 4 years ago)
- Default Branch: master
- Last Pushed: 2023-04-04T00:13:03.000Z (about 2 years ago)
- Last Synced: 2024-12-28T20:06:12.586Z (6 months ago)
- Topics: buffer, file-like, python, python-c-extension, python-extension, sans-io, zero-copy
- Language: C
- Homepage:
- Size: 63.5 KB
- Stars: 14
- Watchers: 3
- Forks: 2
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- Contributing: CONTRIBUTING.md
- License: COPYING
Awesome Lists containing this project
README
# `io‸cursor`
*A [zero-copy](https://en.wikipedia.org/wiki/Zero-copy)
[file-like wrapper](https://docs.python.org/3/library/io.html#io.BufferedIOBase)
for [Python](https://www.python.org/) [byte buffers](https://docs.python.org/3/c-api/buffer.html),
inspired by Rust's [`std::io::Cursor`](https://doc.rust-lang.org/std/io/struct.Cursor.html).*[](https://github.com/althonos/iocursor/actions)
[](https://codecov.io/gh/althonos/iocursor/)
[](https://pypi.org/project/iocursor)
[](https://pypi.org/project/iocursor/#files)
[](https://pypi.org/project/iocursor/#files)
[](https://pypi.org/project/iocursor/#files)
[](https://choosealicense.com/licenses/mit/)
[](https://github.com/althonos/iocursor/)
[](https://github.com/althonos/iocursor/issues)
[](https://pepy.tech/project/iocursor)
[](https://github.com/althonos/iocursor/blob/master/CHANGELOG.md)## 🗺️ Overview
`iocursor.Cursor` lets you wrap an allocated buffer (i.e. a Python object
implementing the [buffer protocol](https://docs.python.org/3/c-api/buffer.html)),
and interfacing with it through the API of a file-like object. It shares
some common points with [`io.BytesIO`](https://docs.python.org/3/library/io.html#io.BytesIO)
but with the following main differences:- *zero-copy* VS *copy*: `Cursor` will not copy the data you give it at
initialisation, while `BytesIO` will. This makes `Cursor` more efficient
when you are using it for read-only operations.
- *static* VS *growable*: `Cursor` will only use the buffer you give it at
static memory, while `BytesIO` will use its dedicated, growable buffer.## 🔧 Installing
Install directly from PyPI, using [pip](https://pip.pypa.io/):
```console
$ pip install iocursor
```Pre-built wheels are available on Linux and OSX for all supported Python3
versions. Otherwise, building from source only requires a working C compiler.## 🧶 Thread-safety
`iocursor.Cursor` instances are not thread-safe. Using several `Cursor`
instances with the same backend memory only for reading should be fine.
Use a lock when interfacing otherwise.## 💡 Examples
- Use `iocursor.Cursor` when you have `bytes` you need to pass to an interface
that only accepts file-like objects. For instance, pass a PNG image decoded
from base64 to PIL, without copy:
```python
import base64
from iocursor import Cursor
from PIL import Imageimgdata = base64.b64decode("iVBORw0KGgoAAAANSUhEU...")
img = Image.open(Cursor(imgdata))
```
- Use `iocursor.Cursor` when you want to use the file-like API to write
to a buffer of known size. For instance, retrieve a file using the
[`pysmb`](https://miketeo.net/blog/projects/pysmb) API, which only accepts
file-like objects:
```python
from SMB.SMBConnection import SMBConnectSMBConnectionsmb = SMBConnection('guest', '', 'client', 'server')
smb.connect("192.168.0.1")info = smb.getAttributes("Music", "The Clash/Rock the Casbah.mp3")
cursor = Cursor(bytearray(shared_file.file_size))
smb.retrieveFile("Music", "The Clash/Rock the Casbah.mp3", cursor)buffer = cursor.getvalue()
```
- Use `iocursor.Cursor` when you want to do direct I/O on a type implementing
the buffer protocol. For instance, initialize a [`numpy`](https://numpy.org/)
[array](https://numpy.org/doc/stable/reference/arrays.html) by writing bytes
to it:
```python
import numpyarray = numpy.empty(4, dtype="int16")
cursor = Cursor(array)
cursor.write(b"\x01\x00\x02\x00\x03\x00\x04\x00")
print(array) # array([1, 2, 3, 4], dtype=int16)
```## 💭 Feedback
### ⚠️ Issue Tracker
Found a bug ? Have an enhancement request ? Head over to the [GitHub issue
tracker](https://github.com/althonos/iocursor/issues) if you need to report
or ask something. If you are filing in on a bug, please include as much
information as you can about the issue, and try to recreate the same bug
in a simple, easily reproducible situation.### 🏗️ Contributing
Contributions are more than welcome! See [`CONTRIBUTING.md`](https://github.com/althonos/iocursor/blob/master/CONTRIBUTING.md) for more details.
## ⚖️ License
This library is provided under the [MIT License](https://choosealicense.com/licenses/mit/).