Skip to main content

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)); False applies natural C alignment.
  • truncate: when False (default) a value longer than its char[N] / cstring[N] field raises PackingError; when True it is silently cut to fit (and still NUL-terminated for cstring).

The same options are available via the binary_struct(endian=..., packed=..., truncate=...) class decorator.

Struct methods

  • obj.pack() -> bytes
  • S.unpack(data) -> S (consumes from the front)
  • S.unpack_tail(data) -> (S, tail) for stream framing
  • S.unpack_from(data, offset) -> S
  • S.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

structed-0.1.0.tar.gz (24.5 kB view details)

Uploaded Source

Built Distribution

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

structed-0.1.0-py3-none-any.whl (23.7 kB view details)

Uploaded Python 3

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

Hashes for structed-0.1.0.tar.gz
Algorithm Hash digest
SHA256 0a1bca0c887b38cb0c866bbac98a2987f326b7fb4d0dba379574fa7a297ab07e
MD5 9efc4b03b5efa75dc0a2be6871ce33f8
BLAKE2b-256 146924e2f0ab2f52d8bc4487e6208d5b1b72894d74bf91b160cbfd6c141c9219

See more details on using hashes here.

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

Hashes for structed-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 780888240de6e24fc43fb9fce0c1d7516c57a4a02137e7eea3091ebb2d03d09d
MD5 03bd18e9761bc31746687a059e5ccbbc
BLAKE2b-256 79acd99188b74832c0a266f335c64680d88c07741d52c1b84b49ceb02d4fdd61

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