Skip to content

Repository files navigation

pystructs

Documentation StatusCIcodecov

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

frompystructsimportStruct, UInt8, UInt16, UInt32, Bytes, Ref, SyncRuleclassPacket(Struct):
classMeta:
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 bytesdata=b"\xde\xad\xbe\xef\x01\x00\x05Hello"packet=Packet.parse(data)
print(packet.magic) # 3735928559 (0xDEADBEEF)print(packet.version) # 1print(packet.payload) # b'Hello'# Create and serializenew_packet=Packet(payload=b"World")
new_packet.sync() # Auto-calculate lengthprint(new_packet.to_bytes())

More Examples

Variable-Length Arrays

frompystructsimportStruct, UInt8, UInt16, Array, Ref, SyncRuleclassScoreBoard(Struct):
classMeta:
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

frompystructsimportStruct, UInt16, BitStruct, Bit, Bits, EmbeddedBitStructclassTCPFlags(BitStruct):
classMeta:
size=1fin=Bit()
syn=Bit()
rst=Bit()
psh=Bit()
ack=Bit()
urg=Bit()
reserved=Bits(2)
classTCPHeader(Struct):
classMeta:
endian="big"src_port=UInt16()
dst_port=UInt16()
flags=EmbeddedBitStruct(TCPFlags)
header=TCPHeader.parse(b"\x00\x50\x1f\x90\x12")
print(header.src_port) # 80print(header.flags.syn) # True

Conditional Fields

frompystructsimportStruct, UInt8, UInt32, Conditional, RefclassVersionedPacket(Struct):
version=UInt8()
# Only present in version 2+extended_header=Conditional(
UInt32(),
when=Ref("version") >=2,
)
data=UInt8()
# Version 1: no extended headerv1=VersionedPacket.parse(b"\x01\x42")
print(v1.extended_header) # None# Version 2: with extended headerv2=VersionedPacket.parse(b"\x02\x00\x00\x00\x01\x42")
print(v2.extended_header) # 1

Tagged Unions (Switch)

frompystructsimportStruct, UInt8, UInt16, UInt32, Switch, RefclassTextPayload(Struct):
length=UInt8()
# text would use Bytes(size=Ref("length"))classBinaryPayload(Struct):
size=UInt16()
# data would use Bytes(size=Ref("size"))classMessage(Struct):
msg_type=UInt8()
payload=Switch(
discriminator=Ref("msg_type"),
cases={
1: TextPayload,
2: BinaryPayload,
},
)

Field Types

CategoryFields
IntegersInt8, UInt8, Int16, UInt16, Int32, UInt32, Int64, UInt64
FloatsFloat32, Float64
BytesFixedBytes, Bytes
StringsFixedString, String, NullTerminatedString
CompositeArray, EmbeddedStruct, Conditional, Switch
SpecialBool, Padding, Flags, Enum
Bit-levelBitStruct, 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

About

Django-like binary parsing library for Python

Topics

Resources

Contributing

Stars

6 stars

Watchers

0 watching

Forks

Used by

Contributors

Languages