Skip to main content

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 struct format 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 Struct object.

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)

Source distribution for self-documenting-struct 0.9.2
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)

Table of built distributions (wheels) for self-documenting-struct 0.9.2
File Interpreter ABI Platform Actions
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.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page