Most projects that use the struct library use raw format strings, which are difficult to understand and remember. This library intuitively wraps the struct library to address this issue. provides dataclasses that define the various struct format string elements, which can then be combined into format strings in a far more consistent and self-documenting manner than they could otherwise.
I wrote this library to aid my reverse engineering efforts.
- On a practical level, I grew tired of copy-pasting unintuitive
structformat strings for common data types like integers and C strings. - On a philosophical level, I believe read-time convenience should be favored above write-time convenience - especially for code that documents file formats.
Old-style struct format string |
Self-documenting struct |
|---|---|
'<H' |
f'{Type.uint16_le}' |
'hhl' |
f'{Primitive.short}{Primitive.short}{Primitive.long}' |
'<10sHHb' |
f'{ByteOrder.little}10{Primitive.fixed_length_string}2{Primitive.ushort}{Primitive.bool}' |
Some simple data types are provided as a sample, with read/write helper functions. The struct library methods are still available, but they are renamed as "raw" methods:
Old-style struct method |
Self-documenting struct method |
|---|---|
struct.pack |
self_documenting_struct.pack.raw |
struct.pack_into |
self_documenting_struct.pack.raw_into |
struct.unpack |
self_documenting_struct.unpack.raw |
struct.unpack_from |
self_documenting_struct.unpack.raw_from |
struct.iter_unpack |
self_documenting_struct.unpack.iter_raw |
struct.calcsize |
self_documenting_struct.calcsize |
Example Usage
You can unpack and pack with the existing simple data types already provided for you.
import self_documenting_struct as struct
with open('C:\WINDOWS\BEAR.EXE', 'rb') as bear_file:
# Since this contains just one element, the tuple is automatically unpacked
# by the uint32_le method.
#
# More readable than struct.unpack_from('<I', bear_file)[0].
an_integer: int = struct.unpack.uint32_le(bear_file)
with open('C:\WINNT\BUNNY32.DLL', 'wb') as bunny_file:
a_packed_integer: bytes = struct.pack.unt32_le(an_integer)
bunny_file.write(a_packed_integer)
Or you can self-documentingly define your own data types using the ByteOrder, Primitive, and Type dataclasses.
(The Primitive dataclass names individual format characters, and the Type dataclass contains common compositions of ByteOrders Primitives.)
import self_documenting_struct as struct
from self_documenting_struct.data_types import Primitive, Type
# This is much more readable than "<Hx?".
foo_bar_type_string: str = f'{Type.uint16_le}{Primitive.pad_byte}{Primitive.bool}'
with open('C:\WINDOWS\BEAR.EXE', 'rb') as bear_file:
# Creates a tuple with the given elements.
# Like usual, you must access the tuple yourself.
foo_bar_int, _, foo_bar_bool = struct.unpack.raw_from(foo_bar_type_string, bear_file)
with open('C:\WINNT\BUNNY32.DLL', 'wb') as bunny_file:
struct.raw_into(foo_bar_type_string, foo_bar)
And, of course, you can define a custom module that extends the self-documenting functionality to your own types.
TODOs
- Add native support for more simple data types useful for reverse engineering.
- Add support for the
Structobject.
Metadata
Release files for self-documenting-struct 0.9.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| self_documenting_struct-0.9.2.tar.gz | 43.1 kB | Without provenance | Details for self_documenting_struct-0.9.2.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| self_documenting_struct-0.9.2-py3-none-any.whl | Python 3 | none | any | Details for self_documenting_struct-0.9.2-py3-none-any.whl |
Total release size: 71.8 kB
Release files / self_documenting_struct-0.9.2.tar.gz
| Download URL | self_documenting_struct-0.9.2.tar.gz |
|---|---|
| Size | 43.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
a3bb038162a27bb1dd2ff85805cabba0ee339a9cf315fc45dfb456f96b54f63c
|
|
BLAKE2b-256 checksum How to use checksums |
b91069c800ddd723bb9889f3bde3cde63032168f36e45c58541fbb79ee0352ab
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/4.0.2 CPython/3.11.7
|
Release files / self_documenting_struct-0.9.2-py3-none-any.whl
| Download URL | self_documenting_struct-0.9.2-py3-none-any.whl |
|---|---|
| Size | 28.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
70900100ab65f05e813416dd947b9fa765dfda399b0807cf44bf3565f5beb9e6
|
|
BLAKE2b-256 checksum How to use checksums |
edbac72f6a482ffa02401399abe24232a3679de9cf10e7639076cf98a8ed490c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/4.0.2 CPython/3.11.7
|
Security for self-documenting-struct 0.9.2
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.