Parse raw bytes into Python data structure and create bytes message from Python data structure.
Project description
bytes-structure
bytes-structure is a Python library that allows you to conveniently define and parse binary protocols and their messages. It supports protocol versioning, enabling you to add new fields with each version while maintaining backward compatibility.
Features
- Simple and Small: A minimal implementation focusing on simplicity and ease of use.
- Based on Stdlib with no 3rd party packages
- Based on stdlib Structure Formats: Uses Python's standard struct format strings, making it familiar to those already accustomed to these formats.
- Easy Protocol Definition: Define binary protocols using intuitive Python classes and Field descriptors.
- Fixed and Variable-Length Fields: Supports both fixed-size and variable-size fields, including those dependent on previous fields.
- Protocol Versioning: Extend protocols with new fields in newer versions using class inheritance.
- Serialization and Deserialization: Pack structured data into raw bytes and unpack raw bytes into structured data.
- Robust Error Handling: Comprehensive error checking and exceptions for reliable protocol parsing.
Installation
- From PyPi
pip install bytes-structure
- From GitHub with editor's mode
git clone https://github.com/bborovskij/bytes_structure.git
cd bytes_structure/
pip install -e .
Usage/Examples
Defining Protocols
Define your binary protocol by creating a class that inherits from ByteStructureBase and declaring Field attributes. Field's format is defined using standard Python struct format strings, ensuring familiarity and ease of use.
from bytes_structure import ByteStructureBase, Field
class ProtocolV1(ByteStructureBase):
ver = Field('>B') # Big-endian unsigned char (1 byte)
word1 = Field('>5s') # Big-endian 5-byte string
Extend your protocol for new versions by subclassing and adding new fields:
class ProtocolV2(ProtocolV1):
length = Field('>B') # Big-endian unsigned char (1 byte)
word2 = Field(lambda self: f'>{self.length}s') # Big-endian string of variable length
Creating Messages
Option 1: From Field Values
Create a message by providing a dictionary of field values. ByteStructure handles packing these values into raw bytes using the specified struct formats.
# For Protocol V1
message_v1 = ProtocolV1(fields_map={'ver': 1, 'word1': b'hello'})
print(message_v1) # Outputs the structured fields
print(message_v1.get_raw()) # Outputs raw bytes: b'\x01hello'
# For Protocol V2
message_v2 = ProtocolV2(fields_map={
'ver': 1,
'word1': b'hello',
'length': 5,
'word2': b'world'
})
print(message_v2)
print(message_v2.get_raw()) # Outputs raw bytes: b'\x01hello\x05world'
Option 2: From Raw Bytes
Create a message by parsing raw bytes. ByteStructure unpacks the raw bytes into structured fields using the specified struct formats.
# For Protocol V1
raw_data_v1 = b'\x01hello'
parsed_message_v1 = ProtocolV1(raw_data_v1)
print(parsed_message_v1)
print(parsed_message_v1.get_raw()) # Outputs raw bytes: b'\x01hello'
# For Protocol V2
raw_data_v2 = b'\x01hello\x05world'
parsed_message_v2 = ProtocolV2(raw_data_v2)
print(parsed_message_v2)
print(parsed_message_v2.get_raw()) # Outputs raw bytes: b'\x01hello\x05world'
Complete Example
See examples/hello_world.
from bytes_structure import ByteStructureBase, Field
class ProtocolV1(ByteStructureBase):
ver = Field('>B') # 1 byte
word1 = Field('>5s') # 5 bytes
class ProtocolV2(ProtocolV1):
length = Field('>B') # 1 byte
word2 = Field(lambda self: f'>{self.length}s') # Variable length field
# Creating a message using field values
message_v2 = ProtocolV2(fields_map={
'ver': 1,
'word1': b'hello',
'length': 5,
'word2': b'world'
})
print(message_v2.ver) # Outputs: 1
print(message_v2.word1) # Outputs: b'hello'
print(message_v2.length) # Outputs: 5
print(message_v2.word2) # Outputs: b'world'
print(message_v2.get_raw()) # Outputs: b'\x01hello\x05world'
# Parsing a message from raw bytes
raw_data = b'\x01hello\x05world'
parsed_message = ProtocolV2(raw_data)
print(parsed_message.ver) # Outputs: 1
print(parsed_message.word1) # Outputs: b'hello'
print(parsed_message.length) # Outputs: 5
print(parsed_message.word2) # Outputs: b'world'
Goals
ByteStructure aims to:
- Conveniently Define Binary Protocols: Simplify the definition of binary messages with an intuitive and declarative approach, keeping the implementation simple and minimal.
- Leverage Well-Known Formats: Utilize Python's built-in struct module and familiar format strings, ensuring ease of understanding and use.
- Support Protocol Versioning: Enable protocols to evolve by adding new fields in new versions without breaking compatibility with older versions.
Why ByteStructure?
- Simplicity: With a minimal codebase, ByteStructure focuses on making binary protocol handling as straightforward as possible.
- Familiarity: By using Python's standard struct format strings, you don't need to learn any new syntax or conventions.
- Flexibility: Supports both fixed and variable-length fields, making it suitable for a wide range of binary protocols.
- Extensibility: Easily extend existing protocols by subclassing and adding new fields.
License
This project is licensed under the MIT License. See MIT.
Contributing
TBD. Not supported at the moment.
Acknowledgements
- Inspired by the need for a flexible yet simple way to handle binary protocols in Python.
- Built upon Python's built-in struct module for reliable and efficient binary data handling.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file bytes_structure-0.1.3.tar.gz.
File metadata
- Download URL: bytes_structure-0.1.3.tar.gz
- Upload date:
- Size: 12.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/5.1.1 CPython/3.12.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3496984eb1dd9a20e698a88e55d81581fc4322d3962f38e30314d8833fbdb6db
|
|
| MD5 |
0c4635e0031f82b307cfb6522261c9b3
|
|
| BLAKE2b-256 |
106157710aa9c55d605bf53d72e4759d15abb6da34a46cee7ef6cb6b139b3a98
|
Provenance
The following attestation bundles were made for bytes_structure-0.1.3.tar.gz:
Publisher:
publish.yml on bborovskij/bytes_structure
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
bytes_structure-0.1.3.tar.gz -
Subject digest:
3496984eb1dd9a20e698a88e55d81581fc4322d3962f38e30314d8833fbdb6db - Sigstore transparency entry: 146490442
- Sigstore integration time:
-
Permalink:
bborovskij/bytes_structure@a49f55b29e1546f68518343b24ed340e212ee88f -
Branch / Tag:
refs/tags/v0.1.3-alpha - Owner: https://github.com/bborovskij
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@a49f55b29e1546f68518343b24ed340e212ee88f -
Trigger Event:
release
-
Statement type:
File details
Details for the file bytes_structure-0.1.3-py3-none-any.whl.
File metadata
- Download URL: bytes_structure-0.1.3-py3-none-any.whl
- Upload date:
- Size: 8.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/5.1.1 CPython/3.12.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
dc0ec3759e51b1e7bd5fbb737f9bc3200e435e5f056e64ad93b5e54eaf0ef823
|
|
| MD5 |
cb45f187fd7ea973f34ca789cd4102ae
|
|
| BLAKE2b-256 |
e62405d46cf9a35b31e66119596a89fe95a0caa74b2c67d2872536a3b9d4a119
|
Provenance
The following attestation bundles were made for bytes_structure-0.1.3-py3-none-any.whl:
Publisher:
publish.yml on bborovskij/bytes_structure
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
bytes_structure-0.1.3-py3-none-any.whl -
Subject digest:
dc0ec3759e51b1e7bd5fbb737f9bc3200e435e5f056e64ad93b5e54eaf0ef823 - Sigstore transparency entry: 146490447
- Sigstore integration time:
-
Permalink:
bborovskij/bytes_structure@a49f55b29e1546f68518343b24ed340e212ee88f -
Branch / Tag:
refs/tags/v0.1.3-alpha - Owner: https://github.com/bborovskij
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@a49f55b29e1546f68518343b24ed340e212ee88f -
Trigger Event:
release
-
Statement type: