Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

18 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

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 Annotated[str, char[N], keep_nulls]; 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].

Nested structs are declared as a bare annotation (inner: Point); each keeps its own endian regardless of the parent struct's byte order.

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

About

C-style packed binary structs for Python. Cross-language friendly serialization.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages