Skip to main content

pystructs

Documentation Status CI codecov

pystructs is a Django-like declarative binary parsing library for Python. Define binary data structures as classes and parse/serialize them with ease.

Features

  • Declarative syntax - Define structs like Django models
  • Bidirectional - Parse binary data and serialize back to bytes
  • Rich field types - Integers, floats, bytes, strings, arrays, and more
  • Bit-level parsing - BitStruct for parsing individual bits
  • Conditional fields - Fields that exist based on runtime conditions
  • Validation system - Built-in and custom validators
  • Zero runtime dependencies - Pure Python implementation

Installation

pip install pystructs
uv add pystructs

Quick Start

from pystructs import Struct, UInt8, UInt16, UInt32, Bytes, Ref, SyncRule

class Packet(Struct):
    class Meta:
        endian = "big"
        sync_rules = [
            SyncRule("length", from_field="payload", compute=len),
        ]

    magic = UInt32(default=0xDEADBEEF)
    version = UInt8(default=1)
    length = UInt16()
    payload = Bytes(size=Ref("length"))

# Parse from bytes
data = b"\xde\xad\xbe\xef\x01\x00\x05Hello"
packet = Packet.parse(data)
print(packet.magic)    # 3735928559 (0xDEADBEEF)
print(packet.version)  # 1
print(packet.payload)  # b'Hello'

# Create and serialize
new_packet = Packet(payload=b"World")
new_packet.sync()  # Auto-calculate length
print(new_packet.to_bytes())

More Examples

Variable-Length Arrays

from pystructs import Struct, UInt8, UInt16, Array, Ref, SyncRule

class ScoreBoard(Struct):
    class Meta:
        sync_rules = [
            SyncRule("count", from_field="scores", compute=len),
        ]

    player_id = UInt16()
    count = UInt8()
    scores = Array(UInt16(), count=Ref("count"))

board = ScoreBoard(player_id=1234, scores=[100, 250, 180])
board.sync()
print(board.to_bytes())  # Serializes with count=3

Bit-Level Parsing

from pystructs import Struct, UInt16, BitStruct, Bit, Bits, EmbeddedBitStruct

class TCPFlags(BitStruct):
    class Meta:
        size = 1

    fin = Bit()
    syn = Bit()
    rst = Bit()
    psh = Bit()
    ack = Bit()
    urg = Bit()
    reserved = Bits(2)

class TCPHeader(Struct):
    class Meta:
        endian = "big"

    src_port = UInt16()
    dst_port = UInt16()
    flags = EmbeddedBitStruct(TCPFlags)

header = TCPHeader.parse(b"\x00\x50\x1f\x90\x12")
print(header.src_port)     # 80
print(header.flags.syn)    # True

Conditional Fields

from pystructs import Struct, UInt8, UInt32, Conditional, Ref

class VersionedPacket(Struct):
    version = UInt8()
    # Only present in version 2+
    extended_header = Conditional(
        UInt32(),
        when=Ref("version") >= 2,
    )
    data = UInt8()

# Version 1: no extended header
v1 = VersionedPacket.parse(b"\x01\x42")
print(v1.extended_header)  # None

# Version 2: with extended header
v2 = VersionedPacket.parse(b"\x02\x00\x00\x00\x01\x42")
print(v2.extended_header)  # 1

Tagged Unions (Switch)

from pystructs import Struct, UInt8, UInt16, UInt32, Switch, Ref

class TextPayload(Struct):
    length = UInt8()
    # text would use Bytes(size=Ref("length"))

class BinaryPayload(Struct):
    size = UInt16()
    # data would use Bytes(size=Ref("size"))

class Message(Struct):
    msg_type = UInt8()
    payload = Switch(
        discriminator=Ref("msg_type"),
        cases={
            1: TextPayload,
            2: BinaryPayload,
        },
    )

Field Types

Category Fields
Integers Int8, UInt8, Int16, UInt16, Int32, UInt32, Int64, UInt64
Floats Float32, Float64
Bytes FixedBytes, Bytes
Strings FixedString, String, NullTerminatedString
Composite Array, EmbeddedStruct, Conditional, Switch
Special Bool, Padding, Flags, Enum
Bit-level BitStruct, Bit, Bits, EmbeddedBitStruct

Documentation

Full documentation is available at Read the Docs.

Contributing

See CONTRIBUTING.md for development setup and contribution guidelines.

License

MIT License

Metadata

Release files for pystructs 0.4.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pystructs 0.4.0
File Size Uploaded Provenance Actions
pystructs-0.4.0.tar.gz 103.6 kB Without provenance Details for pystructs-0.4.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for pystructs 0.4.0
File Interpreter ABI Platform Actions
pystructs-0.4.0-py3-none-any.whl Python 3 none any Details for pystructs-0.4.0-py3-none-any.whl

Total release size: 136.1 kB

Release files / pystructs-0.4.0.tar.gz

Download URL pystructs-0.4.0.tar.gz
Size 103.6 kB
Tags Source
SHA-256 checksum
How to use checksums
6918ffafea0c9f5c9dc9fba31423e9eb4ee4342363dc39800664c6c70ce4f268
BLAKE2b-256 checksum
How to use checksums
01751b5baf9bc866d6b694843a229c82621fb8d9876864a2b41e5cb8d7030608
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.9.20 {"installer":{"name":"uv","version":"0.9.20","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / pystructs-0.4.0-py3-none-any.whl

Download URL pystructs-0.4.0-py3-none-any.whl
Size 32.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
838e4f616160600e8be846106178a70f0beb6659c8dc257dcb3598cbc973fc06
BLAKE2b-256 checksum
How to use checksums
d0d80b0a897332d5446e4c72b3a5f1f026acc016d931bba85f505280a34181da
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.9.20 {"installer":{"name":"uv","version":"0.9.20","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Security for pystructs 0.4.0

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