Core API: Structs and Sequences

construct.Struct(*subcons, **kw)

A sequence of usually named constructs, similar to structs in C. The elements are parsed and built in the order they are defined.

Some fields do not need to be named, since they are built from None anyway. See Const Padding Pass Terminated.

See also

Can be nested easily, and embedded using Embedded() wrapper that merges members into parent’s members.

Parameters:subcons – a sequence of subconstructs that make up this structure

Example:

>>> Struct("a"/Int8ul, "data"/Bytes(2), "data2"/Bytes(this.a)).parse(b"\x01abc")
Container(a=1)(data=b'ab')(data2=b'c')
>>> Struct("a"/Int8ul, "data"/Bytes(2), "data2"/Bytes(this.a)).build(_)
b'\x01abc'
>>> Struct("a"/Int8ul, "data"/Bytes(2), "data2"/Bytes(this.a)).build(dict(a=5, data=b"??", data2=b"hello"))
b'\x05??hello'

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

Note that this syntax works ONLY on python 3.6 due to unordered keyword arguments:
>>> Struct(a=Byte, b=Byte, c=Byte, d=Byte)
construct.Sequence(*subcons, **kw)

A sequence of unnamed constructs. The elements are parsed and built in the order they are defined.

See also

Can be nested easily, and embedded using Embedded() wrapper that merges entries into parent’s entries.

Parameters:subcons – a sequence of subconstructs that make up this sequence

Example:

>>> (Byte >> Byte).build([1, 2])
b'\x01\x02'
>>> (Byte >> Byte).parse(_)
[1, 2]
>>> (Byte >> Byte).sizeof()
2

>>> Sequence(Byte, CString(), Float32b).build([255, b"hello", 123])
b'\xffhello\x00B\xf6\x00\x00'
>>> Sequence(Byte, CString(), Float32b).parse(_)
[255, b'hello', 123.0]
construct.Embedded(subcon)

Embeds a struct into the enclosing struct, merging fields. Can also embed sequences into sequences. Name is also inherited.

Parameters:subcon – the struct to embed

Example:

>>> Struct("a"/Byte, Embedded(Struct("b"/Byte)), "c"/Byte).parse(b"abc")
Container(a=97)(b=98)(c=99)
>>> Struct("a"/Byte, Embedded(Struct("b"/Byte)), "c"/Byte).build(_)
b'abc'
construct.StopIf(condfunc)

Checks for a condition, and stops a Struct Sequence Range from parsing or building.

Warning

May break sizeof methods. Unsure.

Example:

Struct('x'/Byte, StopIf(this.x == 0), 'y'/Byte)

Sequence('x'/Byte, StopIf(this.x == 0), 'y'/Byte)

GreedyRange(FocusedSeq(0, 'x'/Byte, StopIf(this.x == 0)))
construct.Union(parsefrom, *subcons, **kw)

Treats the same data as multiple constructs (similar to C union statement) so you can “look” at the data in multiple views.

When parsing, all fields read the same data bytes, but stream remains at initial offset if None, unless parsefrom selects a subcon by index or name. When building, the first subcon that can find an entry in the dict (or builds from None, so it does not require an entry) is automatically selected.

Warning

If you skip the parsefrom parameter then stream will be left back at the starting offset. Many users fail to use this class properly.

Parameters:
  • parsefrom – how to leave stream after parsing, can be integer index or string name selecting a subcon, None (leaves stream at initial offset, the default), a context lambda returning either of previously mentioned
  • subcons – subconstructs (order and name sensitive)

Example:

>>> Union(0, "raw"/Bytes(8), "ints"/Int32ub[2], "shorts"/Int16ub[4], "chars"/Byte[8]).parse(b"12345678")
Container(raw=b'12345678')(ints=[825373492, 892745528])(shorts=[12594, 13108, 13622, 14136])(chars=[49, 50, 51, 52, 53, 54, 55, 56])

>>> Union(0, "raw"/Bytes(8), "ints"/Int32ub[2], "shorts"/Int16ub[4], "chars"/Byte[8]).build(dict(chars=range(8)))
b'\x00\x01\x02\x03\x04\x05\x06\x07'

Note that this syntax works ONLY on python 3.6 due to unordered keyword arguments:
>>> Union(0, raw=Bytes(8), ints=Int32ub[2], shorts=Int16ub[4], chars=Byte[8])
>>> Union(0, raw=Bytes(8), ints=Int32ub[2], shorts=Int16ub[4], chars=Byte[8])
construct.Select(*subcons, **kw)

Selects the first matching subconstruct. It will literally try each of the subconstructs, until one matches.

Parameters:
  • subcons – the subcons to try (order sensitive)
  • includename – indicates whether to include the name of the selected subcon in the return value of parsing, default is false

Example:

>>> Select(Int32ub, CString(encoding="utf8")).build(1)
b'\x00\x00\x00\x01'
>>> Select(Int32ub, CString(encoding="utf8")).build("Афон")
b'\xd0\x90\xd1\x84\xd0\xbe\xd0\xbd\x00'

Note that this syntax works ONLY on python 3.6 due to unordered keyword arguments:
>>> Select(num=Int32ub, text=CString(encoding="utf8"))
construct.Optional(subcon)

Makes an optional construct, that tries to parse the subcon. If parsing fails, returns None. If building fails, writes nothing.

Note: sizeof returns subcon size, although no bytes could be consumed or produced. Just something to consider.

Parameters:subcon – the subcon to optionally parse or build

Example:

>>> Optional(Int64ul).parse(b"1234")
>>> Optional(Int64ul).parse(b"12345678")
4050765991979987505

>>> Optional(Int64ul).build(1)
b'\x01\x00\x00\x00\x00\x00\x00\x00'
>>> Optional(Int64ul).build("1")
b''
construct.If(predicate, subcon)

An if-then conditional construct. If the predicate indicates True, the subcon will be used for parsing and building, otherwise parsing returns None and building is no-op.

Parameters:
  • predicate – a function taking context and returning a bool
  • subcon – the subcon that will be used if the predicate returns True

Example:

>>> If(this.x > 0, Byte).build(255, dict(x=1))
b'\xff'
>>> If(this.x > 0, Byte).build(255, dict(x=0))
b''
construct.IfThenElse(predicate, thensubcon, elsesubcon)

An if-then-else conditional construct. If the predicate indicates True, thensubcon will be used, otherwise elsesubcon will be used.

Parameters:
  • predicate – a function taking context and returning a bool
  • thensubcon – the subcon that will be used if the predicate indicates True
  • elsesubcon – the subcon that will be used if the predicate indicates False

Example:

>>> IfThenElse(this.x > 0, VarInt, Byte).build(255, dict(x=1))
b'\xff\x01'
>>> IfThenElse(this.x > 0, VarInt, Byte).build(255, dict(x=0))
b'\xff'
construct.Switch(keyfunc, cases, default=<NoDefault: None>, includekey=False)

A conditional branch. Switch will choose the case to follow based on the return value of keyfunc. If no case is matched, and no default value is given, SwitchError will be raised.

Warning

You can use Embedded(Switch(...)) but not Switch(Embedded(...)). Sames applies to If and IfThenElse macros.

Parameters:
  • keyfunc – a context function that returns a key which will choose a case, or a constant
  • cases – a dictionary mapping keys to subcons
  • default – a default field to use when the key is not found in the cases. if not supplied, an exception will be raised when the key is not found. Pass can be used for do-nothing
  • includekey – whether to include the key in the return value of parsing, defualt is False

Example:

>>> Switch(this.n, { 1:Byte, 2:Int32ub }).build(5, dict(n=1))
b'\x05'
>>> Switch(this.n, { 1:Byte, 2:Int32ub }).build(5, dict(n=2))
b'\x00\x00\x00\x05'
construct.AlignedStruct(modulus, *subcons, **kw)

Makes a structure where each field is aligned to the same modulus.

See also

Uses Aligned() and ~construct.core.Struct.

Parameters:
  • modulus – passed to each member
  • *subcons – the subcons that make up this structure
  • pattern – optional, keyword parameter passed to each member

Example:

>>> AlignedStruct(4, "a"/Int8ub, "b"/Int16ub).build(dict(a=1,b=5))
b'\x01\x00\x00\x00\x00\x05\x00\x00'
>>> AlignedStruct(4, "a"/Int8ub, "b"/Int16ub).parse(_)
Container(a=1)(b=5)
>>> AlignedStruct(4, "a"/Int8ub, "b"/Int16ub).sizeof()
8
construct.BitStruct(*subcons)

Makes a structure inside a Bitwise.

See also

Uses Bitwise() and Struct().

Parameters:*subcons – the subcons that make up this structure

Example:

>>> BitStruct("field"/Octet).build(dict(field=5))
b'\x05'
>>> BitStruct("field"/Octet).parse(_)
Container(field=5)
>>> BitStruct("field"/Octet).sizeof()
1

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

Makes an embedded BitStruct.

See also

Uses Bitwise() and Embedded() and Struct().

Parameters:*subcons – the subcons that make up this structure