Core API: Structs and Sequences

construct.Struct(*subcons, **subconskw)

Sequence of usually named constructs, similar to structs in C. The members are parsed and build in the order they are defined. If a member is anonymous (its name is None) then it gets parsed and the value discarded, or it gets build from nothing (from None).

Some fields do not need to be named, since they are built without value anyway. See: Const Padding Check Error Pass Terminated Seek Tell for examples of such fields.

Operator + can also be used to make Structs (although not recommended).

Parses into a Container (dict with attribute and key access) where keys match subcon names. Builds from a dict (not necessarily a Container) where each member gets a value from the dict matching the subcon name. If field has build-from-none flag, it gets build even when there is no matching entry in the dict. Size is the sum of all subcon sizes, unless any subcon raises SizeofError.

This class does context nesting, meaning its members are given access to a new dictionary where the “_” entry points to the outer context. When parsing, each member gets parsed and subcon parse return value is inserted into context under matching key only if the member was named. When building, the matching entry gets inserted into context before subcon gets build, and if subcon build returns a new value (not None) that gets replaced in the context.

This class exposes subcons as attributes. You can refer to subcons that were inlined (and therefore do not exist as variable in the namespace) by accessing the struct attributes, under same name. Also note that compiler does not support this feature. See examples.

This class exposes subcons in the context. You can refer to subcons that were inlined (and therefore do not exist as variable in the namespace) within other inlined fields using the context. Note that you need to use a lambda (this expression is not supported). Also note that compiler does not support this feature. See examples.

This class supports stopping. If StopIf field is a member, and it evaluates its lambda as positive, this class ends parsing or building as successful without processing further fields.

Parameters:
  • *subcons – Construct instances, list of members, some can be anonymous

  • **subconskw – Construct instances, list of members (requires Python 3.6)

Raises:
  • StreamError – requested reading negative amount, could not read enough bytes, requested writing different amount than actual data, or could not write all bytes

  • KeyError – building a subcon but found no corresponding key in dictionary

Example:

>>> d = Struct("num"/Int8ub, "data"/Bytes(this.num))
>>> d.parse(b"\x04DATA")
Container(num=4, data=b"DATA")
>>> d.build(dict(num=4, data=b"DATA"))
b"\x04DATA"

>>> d = Struct(Const(b"MZ"), Padding(2), Pass, Terminated)
>>> d.build({})
b'MZ\x00\x00'
>>> d.parse(_)
Container()
>>> d.sizeof()
4

>>> d = Struct(
...     "animal" / Enum(Byte, giraffe=1),
... )
>>> d.animal.giraffe
'giraffe'
>>> d = Struct(
...     "count" / Byte,
...     "data" / Bytes(lambda this: this.count - this._subcons.count.sizeof()),
... )
>>> d.build(dict(count=3, data=b"12"))
b'\x0312'

Alternative syntax (not recommended):
>>> ("a"/Byte + "b"/Byte + "c"/Byte + "d"/Byte)

Alternative syntax, but requires Python 3.6 or any PyPy:
>>> Struct(a=Byte, b=Byte, c=Byte, d=Byte)
construct.Sequence(*subcons, **subconskw)

Sequence of usually un-named constructs. The members are parsed and build in the order they are defined. If a member is named, its parsed value gets inserted into the context. This allows using members that refer to previous members.

Operator >> can also be used to make Sequences (although not recommended).

Parses into a ListContainer (list with pretty-printing) where values are in same order as subcons. Builds from a list (not necessarily a ListContainer) where each subcon is given the element at respective position. Size is the sum of all subcon sizes, unless any subcon raises SizeofError.

This class does context nesting, meaning its members are given access to a new dictionary where the “_” entry points to the outer context. When parsing, each member gets parsed and subcon parse return value is inserted into context under matching key only if the member was named. When building, the matching entry gets inserted into context before subcon gets build, and if subcon build returns a new value (not None) that gets replaced in the context.

This class exposes subcons as attributes. You can refer to subcons that were inlined (and therefore do not exist as variable in the namespace) by accessing the struct attributes, under same name. Also note that compiler does not support this feature. See examples.

This class exposes subcons in the context. You can refer to subcons that were inlined (and therefore do not exist as variable in the namespace) within other inlined fields using the context. Note that you need to use a lambda (this expression is not supported). Also note that compiler does not support this feature. See examples.

This class supports stopping. If StopIf field is a member, and it evaluates its lambda as positive, this class ends parsing or building as successful without processing further fields.

Parameters:
  • *subcons – Construct instances, list of members, some can be named

  • **subconskw – Construct instances, list of members (requires Python 3.6)

Raises:
  • StreamError – requested reading negative amount, could not read enough bytes, requested writing different amount than actual data, or could not write all bytes

  • KeyError – building a subcon but found no corresponding key in dictionary

Example:

>>> d = Sequence(Byte, Float32b)
>>> d.build([0, 1.23])
b'\x00?\x9dp\xa4'
>>> d.parse(_)
[0, 1.2300000190734863] # a ListContainer

>>> d = Sequence(
...     "animal" / Enum(Byte, giraffe=1),
... )
>>> d.animal.giraffe
'giraffe'
>>> d = Sequence(
...     "count" / Byte,
...     "data" / Bytes(lambda this: this.count - this._subcons.count.sizeof()),
... )
>>> d.build([3, b"12"])
b'\x0312'

Alternative syntax (not recommended):
>>> (Byte >> "Byte >> "c"/Byte >> "d"/Byte)

Alternative syntax, but requires Python 3.6 or any PyPy:
>>> Sequence(a=Byte, b=Byte, c=Byte, d=Byte)
construct.AlignedStruct(modulus, *subcons, **subconskw)

Makes a structure where each field is aligned to the same modulus (it is a struct of aligned fields, NOT an aligned struct).

See Aligned and Struct for semantics and raisable exceptions.

Parameters:
  • modulus – integer or context lambda, passed to each member

  • *subcons – Construct instances, list of members, some can be anonymous

  • **subconskw – Construct instances, list of members (requires Python 3.6)

Example:

>>> d = AlignedStruct(4, "a"/Int8ub, "b"/Int16ub)
>>> d.build(dict(a=0xFF,b=0xFFFF))
b'\xff\x00\x00\x00\xff\xff\x00\x00'
construct.BitStruct(*subcons, **subconskw)

Makes a structure inside a Bitwise.

See Bitwise and Struct for semantics and raisable exceptions.

Parameters:
  • *subcons – Construct instances, list of members, some can be anonymous

  • **subconskw – Construct instances, list of members (requires Python 3.6)

Example:

BitStruct  <-->  Bitwise(Struct(...))

>>> d = BitStruct(
...     "a" / Flag,
...     "b" / Nibble,
...     "c" / BitsInteger(10),
...     "d" / Padding(1),
... )
>>> d.parse(b"\xbe\xef")
Container(a=True, b=7, c=887, d=None)
>>> d.sizeof()
2