Skip to main content

c-like struct implementation for human

Project description

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

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pystructs-0.4.0.tar.gz (103.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pystructs-0.4.0-py3-none-any.whl (32.6 kB view details)

Uploaded Python 3

File details

Details for the file pystructs-0.4.0.tar.gz.

File metadata

  • Download URL: pystructs-0.4.0.tar.gz
  • Upload date:
  • Size: 103.6 kB
  • Tags: Source
  • Uploaded using 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}

File hashes

Hashes for pystructs-0.4.0.tar.gz
Algorithm Hash digest
SHA256 6918ffafea0c9f5c9dc9fba31423e9eb4ee4342363dc39800664c6c70ce4f268
MD5 da74ca734c73e39d54643c615259ec66
BLAKE2b-256 01751b5baf9bc866d6b694843a229c82621fb8d9876864a2b41e5cb8d7030608

See more details on using hashes here.

File details

Details for the file pystructs-0.4.0-py3-none-any.whl.

File metadata

  • Download URL: pystructs-0.4.0-py3-none-any.whl
  • Upload date:
  • Size: 32.6 kB
  • Tags: Python 3
  • Uploaded using 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}

File hashes

Hashes for pystructs-0.4.0-py3-none-any.whl
Algorithm Hash digest
SHA256 838e4f616160600e8be846106178a70f0beb6659c8dc257dcb3598cbc973fc06
MD5 0565bf0ae0ba2f047b226df87f00ea4e
BLAKE2b-256 d0d80b0a897332d5446e4c72b3a5f1f026acc016d931bba85f505280a34181da

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page