structed
C-style packed binary structs for Python, declared with type annotations.
Zero runtime dependencies, byte-for-byte compatible with C struct
layouts (including __attribute__((packed))), and friendly to
cross-language interop and network protocols.
Install
pip install structed
Quick start
from typing import Annotated
from structed import Endian, Struct, uint8_t, uint32_t, char, cstring, cppstring
class Header(Struct, endian=Endian.LITTLE):
magic: Annotated[bytes, char[4]] # fixed-width, NUL-padded
version: Annotated[int, uint8_t]
count: Annotated[int, uint32_t]
note: Annotated[str, cstring[16]] # NUL-terminated C string
data: Annotated[str, cppstring] # length-prefixed string
binary = Header(magic=b"PROT", version=1, count=3, note="hi", data="x").pack()
header = Header.unpack(binary)
obj, rest = Header.unpack_tail(binary + b"more") # stream framing
Field types
| Marker | Wire type | Python type | Notes |
|---|---|---|---|
uint8_t .. uint64_t, int8_t .. int64_t |
fixed-width int | int |
byte order follows the struct's endian |
float32, float64 |
IEEE-754 | float |
|
char[N] |
char buf[N] |
bytes or str |
fixed width; pads with NULs |
char[N] + keep_nulls |
as above | str |
keeps embedded NULs on unpack |
cstring[N] |
C string | str or bytes |
N includes the NUL terminator; unpack stops at the first NUL |
cppstring |
u32 length + payload |
str or bytes |
length-prefixed; variable-length |
Array(N, T), list[T], or scalar * N |
T arr[N] |
list |
fixed-size array of primitives or structs |
| nested struct class | struct T {...} |
instance | a Struct subclass used bare as an annotation |
Annotations use typing.Annotated: Annotated[int, uint16_t],
Annotated[str, cstring[16]], Annotated[str, cppstring].
Arrays
An array packs N elements back-to-back and round-trips as a list. The
element type is given explicitly, inferred from a list[T] annotation, or
repeated with *:
class S(Struct, endian=Endian.LITTLE):
flags: Annotated[list[int], Array(4, uint16_t)] # explicit
ages: Annotated[list[int], uint8_t * 2] # shorthand for Array(2, uint8_t)
pts: Annotated[list[Point], Array(3)] # array of nested structs
s = S(flags=[1, 2, 3, 4], ages=[12, 13], pts=[...])
assert s.flags == [1, 2, 3, 4] and s.ages == [12, 13]
The value must have exactly N elements, otherwise packing raises
PackingError. Arrays cannot hold variable-length (cppstring) elements.
Struct options
class Packet(Struct, endian=Endian.BIG, packed=True, truncate=False):
...
endian:Endian.LITTLE,Endian.BIG,Endian.NATIVE,Endian.NETWORK.packed:True(default) lays fields back-to-back like C__attribute__((packed));Falseapplies natural C alignment.truncate: whenFalse(default) a value longer than itschar[N]/cstring[N]field raisesPackingError; whenTrueit is silently cut to fit (and still NUL-terminated forcstring).
The same options are available via the binary_struct(endian=..., packed=..., truncate=...) class decorator.
Struct methods
obj.pack()->bytesS.unpack(data)->S(consumes from the front)S.unpack_tail(data)->(S, tail)for stream framingS.unpack_from(data, offset)->SS.sizeof()->int(fixed minimum for variable-length structs)
Variable-length fields
cppstring fields are length-prefixed and may be followed by fixed-size
fields; parsing always resumes right after the payload. Only one variable
field is allowed per struct, packed=True is required, and a struct with a
variable field cannot be nested or used as an array element.
Development
make venv # create .venv and install editable + deps
make check # run tests + syntax + type checks
make example # run examples/
make build-release # verify, then build sdist + wheel
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file structed-0.1.0.tar.gz.
File metadata
- Download URL: structed-0.1.0.tar.gz
- Upload date:
- Size: 24.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0a1bca0c887b38cb0c866bbac98a2987f326b7fb4d0dba379574fa7a297ab07e
|
|
| MD5 |
9efc4b03b5efa75dc0a2be6871ce33f8
|
|
| BLAKE2b-256 |
146924e2f0ab2f52d8bc4487e6208d5b1b72894d74bf91b160cbfd6c141c9219
|
File details
Details for the file structed-0.1.0-py3-none-any.whl.
File metadata
- Download URL: structed-0.1.0-py3-none-any.whl
- Upload date:
- Size: 23.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
780888240de6e24fc43fb9fce0c1d7516c57a4a02137e7eea3091ebb2d03d09d
|
|
| MD5 |
03bd18e9761bc31746687a059e5ccbbc
|
|
| BLAKE2b-256 |
79acd99188b74832c0a266f335c64680d88c07741d52c1b84b49ceb02d4fdd61
|