construct.core – entire module

exception construct.core.AdaptationError
class construct.core.Adapter(subcon)

Abstract adapter class.

Needs to implement _decode() for parsing and _encode() for building.

Parameters:subcon – Construct instance
class construct.core.Aligned(modulus, subcon, pattern='x00')

Appends additional null bytes to achieve a length that is shortest multiple of a modulus.

Note that subcon can actually be variable size, it is the eventual amount of bytes that is read or written during parsing or building that determines actual padding.

Parsing first parses subcon, then consumes an amount of bytes to sum up to specified length, and discards it. Building first builds subcon, then writes specified pattern byte to sum up to specified length. Size is subcon size plus modulo remainder, unless SizeofError was raised.

Parameters:
  • modulus – integer or context lambda, modulus to final length
  • subcon – Construct instance
  • pattern – optional, b-character, padding pattern, default is \x00
Raises:
  • StreamError – requested reading negative amount, could not read enough bytes, requested writing different amount than actual data, or could not write all bytes
  • PaddingError – modulus was less than 2
  • PaddingError – pattern was not bytes (b-character)

Can propagate any exception from the lambda, possibly non-ConstructError.

Example:

>>> d = Aligned(4, Int16ub)
>>> d.parse(b'\x00\x01\x00\x00')
1
>>> d.sizeof()
4
construct.core.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'
class construct.core.Array(count, subcon, discard=False)

Homogenous array of elements, similar to C# generic T[].

Parses into a ListContainer (a list). Parsing and building processes an exact amount of elements. If given list has more or less than count elements, raises RangeError. Size is defined as count multiplied by subcon size, but only if subcon is fixed size.

Operator [] can be used to make Array instances (recommended syntax).

Parameters:
  • count – integer or context lambda, strict amount of elements
  • subcon – Construct instance, subcon to process individual elements
  • discard – optional, bool, if set then parsing returns empty list
Raises:
  • StreamError – requested reading negative amount, could not read enough bytes, requested writing different amount than actual data, or could not write all bytes
  • RangeError – specified count is not valid
  • RangeError – given object has different length than specified count

Can propagate any exception from the lambdas, possibly non-ConstructError.

Example:

>>> d = Array(5, Byte) or Byte[5]
>>> d.build(range(5))
b'\x00\x01\x02\x03\x04'
>>> d.parse(_)
[0, 1, 2, 3, 4]
construct.core.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
class construct.core.BitsInteger(length, signed=False, swapped=False)

Field that packs arbitrarily large (or small) integers. Some fields (Bit Nibble Octet) use this class. Must be enclosed in Bitwise context.

Parses into an integer. Builds from an integer into specified bit count and endianness. Size (in bits) is specified in ctor.

Note that little-endianness is only defined for multiples of 8 bits.

Analog to BytesInteger that operates on bytes. In fact, BytesInteger(n) is equivalent to Bitwise(BitsInteger(8*n)) and BitsInteger(n) is equivalent to Bytewise(BytesInteger(n//8))) .

Parameters:
  • length – integer or context lambda, number of bits in the field
  • signed – bool, whether the value is signed (two’s complement), default is False (unsigned)
  • swapped – bool, whether to swap byte order (little endian), default is False (big endian)
Raises:
  • StreamError – requested reading negative amount, could not read enough bytes, requested writing different amount than actual data, or could not write all bytes
  • IntegerError – lenght is negative, given a negative value when field is not signed, or not an integer

Can propagate any exception from the lambda, possibly non-ConstructError.

Example:

>>> d = Bitwise(BitsInteger(8)) or Bitwise(Octet)
>>> d.parse(b"\x10")
16
>>> d.build(255)
b'\xff'
>>> d.sizeof()
1
construct.core.BitsSwapped(subcon)

Swaps the bit order within each byte within boundaries of given subcon. Does NOT require a fixed sized subcon.

Parameters:subcon – Construct instance, subcon on top of bit swapped bytes
Raises:SizeofError – compiler could not compute subcon size

See Transformed and Restreamed for raisable exceptions.

Example:

>>> d = Bitwise(Bytes(8))
>>> d.parse(b"\x01")
'\x00\x00\x00\x00\x00\x00\x00\x01'
>>>> BitsSwapped(d).parse(b"\x01")
'\x01\x00\x00\x00\x00\x00\x00\x00'
class construct.core.BitwisableString

Used internally.

construct.core.Bitwise(subcon)

Converts the stream from bytes to bits, and passes the bitstream to underlying subcon. Bitstream is a stream that contains 8 times as many bytes, and each byte is either \x00 or \x01 (in documentation those bytes are called bits).

Parsing building and size are deferred to subcon, although size gets divided by 8.

Parameters:subcon – Construct instance, any field that works with bits (like BitsInteger) or is bit-byte agnostic (like Struct or Flag)

See Transformed and Restreamed for raisable exceptions.

Example:

>>> d = Bitwise(Struct(
...     'a' / Nibble,
...     'b' / Bytewise(Float32b),
...     'c' / Padding(4),
... ))
>>> d.parse(bytes(5))
Container(a=0)(b=0.0)(c=None)
>>> d.sizeof()
5
construct.core.ByteSwapped(subcon)

Swaps the byte order within boundaries of given subcon. Requires a fixed sized subcon.

Parameters:subcon – Construct instance, subcon on top of byte swapped bytes
Raises:SizeofError – ctor or compiler could not compute subcon size

See Transformed and Restreamed for raisable exceptions.

Example:

Int24ul <--> ByteSwapped(Int24ub) <--> BytesInteger(3, swapped=True) <--> ByteSwapped(BytesInteger(3))
class construct.core.Bytes(length)

Field consisting of a specified number of bytes.

Parses into a bytes (of given length). Builds into the stream directly (but checks that given object matches specified length). Can also build from an integer for convenience (although BytesInteger should be used instead). Size is the specified length.

Parameters:

length – integer or context lambda

Raises:
  • StreamError – requested reading negative amount, could not read enough bytes, requested writing different amount than actual data, or could not write all bytes
  • StringError – building from non-bytes value, perhaps unicode

Can propagate any exception from the lambda, possibly non-ConstructError.

Example:

>>> d = Bytes(4)
>>> d.parse(b'beef')
b'beef'
>>> d.build(b'beef')
b'beef'
>>> d.build(0)
b'\x00\x00\x00\x00'
>>> d.sizeof()
4

>>> d = Struct(
...     "length" / Int8ub,
...     "data" / Bytes(this.length),
... )
>>> d.parse(b"\x04beef")
Container(length=4)(data=b'beef')
>>> d.sizeof()
construct.core.SizeofError: cannot calculate size, key not found in context
class construct.core.BytesInteger(length, signed=False, swapped=False)

Field that packs arbitrarily large integers. Some Int24* fields use this class.

Parses into an integer. Builds from an integer into specified byte count and endianness. Size is specified in ctor.

Analog to BitsInteger that operates on bits. In fact, BytesInteger(n) is equivalent to Bitwise(BitsInteger(8*n)) and BitsInteger(n) is equivalent to Bytewise(BytesInteger(n//8))) .

Parameters:
  • length – integer or context lambda, number of bytes in the field
  • signed – bool, whether the value is signed (two’s complement), default is False (unsigned)
  • swapped – bool, whether to swap byte order (little endian), default is False (big endian)
Raises:
  • StreamError – requested reading negative amount, could not read enough bytes, requested writing different amount than actual data, or could not write all bytes
  • IntegerError – lenght is negative, given a negative value when field is not signed, or not an integer

Can propagate any exception from the lambda, possibly non-ConstructError.

Example:

>>> d = BytesInteger(4) or Int32ub
>>> d.parse(b"abcd")
1633837924
>>> d.build(1)
b'\x00\x00\x00\x01'
>>> d.sizeof()
4
construct.core.Bytewise(subcon)

Converts the bitstream back to normal byte stream. Must be used within Bitwise.

Parsing building and size are deferred to subcon, although size gets multiplied by 8.

Parameters:subcon – Construct instance, any field that works with bytes or is bit-byte agnostic

See Transformed and Restreamed for raisable exceptions.

Example:

>>> d = Bitwise(Struct(
...     'a' / Nibble,
...     'b' / Bytewise(Float32b),
...     'c' / Padding(4),
... ))
>>> d.parse(bytes(5))
Container(a=0)(b=0.0)(c=None)
>>> d.sizeof()
5
construct.core.CString(encoding)

String ending in a terminating null byte (or null bytes in case of UTF16 UTF32).

Warning

String and CString only support encodings explicitly listed in possiblestringencodings .

Parameters:

encoding – string like: utf8 utf16 utf32 ascii

Raises:

Example:

>>> d = CString("utf8")
>>> d.build(u"Афон")
b'\xd0\x90\xd1\x84\xd0\xbe\xd0\xbd\x00'
>>> d.parse(_)
u'Афон'
exception construct.core.CancelParsing
class construct.core.Check(func)

Checks for a condition, and raises CheckError if the check fails.

Parsing and building return nothing (but check the condition). Size is 0 because stream is unaffected.

Parameters:func – bool or context lambda, that gets run on parsing and building
Raises:CheckError – lambda returned false

Can propagate any exception from the lambda, possibly non-ConstructError.

Example:

Check(lambda ctx: len(ctx.payload.data) == ctx.payload_len)
Check(len_(this.payload.data) == this.payload_len)
exception construct.core.CheckError
class construct.core.Checksum(checksumfield, hashfunc, bytesfunc)

Field that is build or validated by a hash of a given byte range. Usually used with RawCopy .

Parsing compares parsed subcon checksumfield with a context entry provided by bytesfunc and transformed by hashfunc. Building fetches the contect entry, transforms it, then writes is using subcon. Size is same as subcon.

Parameters:
  • checksumfield – a subcon field that reads the checksum, usually Bytes(int)
  • hashfunc – function that takes bytes and returns whatever checksumfield takes when building, usually from hashlib module
  • bytesfunc – context lambda that returns bytes (or object) to be hashed, usually like this.rawcopy1.data
Raises:

ChecksumError – parsing and actual checksum does not match actual data

Can propagate any exception from the lambdas, possibly non-ConstructError.

Example:

import hashlib
d = Struct(
    "fields" / RawCopy(Struct(
        Padding(1000),
    )),
    "checksum" / Checksum(Bytes(64),
        lambda data: hashlib.sha512(data).digest(),
        this.fields.data),
)
d.build(dict(fields=dict(value={})))
import hashlib
d = Struct(
    "offset" / Tell,
    "checksum" / Padding(64),
    "fields" / RawCopy(Struct(
        Padding(1000),
    )),
    "checksum" / Pointer(this.offset, Checksum(Bytes(64),
        lambda data: hashlib.sha512(data).digest(),
        this.fields.data)),
)
d.build(dict(fields=dict(value={})))
exception construct.core.ChecksumError
class construct.core.Compiled(source, defersubcon, parsefunc)

Used internally.

benchmark(sampledata, filename=None)

Measures performance of your construct (its parsing and building runtime), both for the original instance and the compiled instance. Uses timeit module, over at min 1 sample, and at max over 1 second time.

Optionally, results are saved to a text file for later inspection. Otherwise you can print the result string to terminal.

Also this method checks correctness, by comparing parsing/building results from both instances.

Parameters:
  • sampledata – bytes, a valid blob parsable by this construct
  • filename – optional, string, source is saved to that file
Returns:

string containing measurements

compile(filename=None)

Transforms a construct into another construct that does same thing (has same parsing and building semantics) but is much faster when parsing. Already compiled instances just compile into itself.

Optionally, partial source code can be saved to a text file. This is meant only to inspect the generated code, not to import it from external scripts.

Returns:Compiled instance
class construct.core.Compressed(subcon, encoding, level=None)

Compresses and decompresses underlying stream when processing subcon. When parsing, entire stream is consumed. When building, puts compressed bytes without marking the end. This construct should be used with Prefixed .

Parsing and building transforms all bytes using a specified codec. Since data is processed until EOF, it behaves similar to GreedyBytes. Size is undefined.

Parameters:
  • subcon – Construct instance, subcon used for storing the value
  • encoding – string, any of module names like zlib/gzip/bzip2/lzma, otherwise any of codecs module bytes<->bytes encodings, each codec usually requires some Python version
  • level – optional, integer between 0..9, although lzma discards it, some encoders allow different compression levels
Raises:
  • ImportError – needed module could not be imported by ctor
  • StreamError – stream failed when reading until EOF

Example:

>>> d = Prefixed(VarInt, Compressed(GreedyBytes, "zlib"))
>>> d.build(bytes(100))
b'\x0cx\x9cc`\xa0=\x00\x00\x00d\x00\x01'
class construct.core.Computed(func)

Field computing a value from the context dictionary or some outer source like os.urandom or random module. Underlying byte stream is unaffected. The source can be non-deterministic.

Parsing and Building return the value returned by the context lambda (although a constant value can also be used). Size is defined as 0 because parsing and building does not consume or produce bytes into the stream.

Parameters:func – context lambda or constant value

Can propagate any exception from the lambda, possibly non-ConstructError.

Example::
>>> d = Struct(
...     "width" / Byte,
...     "height" / Byte,
...     "total" / Computed(this.width * this.height),
... )
>>> d.build(dict(width=4,height=5))
b'\x04\x05'
>>> d.parse(b"12")
Container(width=49, height=50, total=2450)
>>> d = Computed(7)
>>> d.parse(b"")
7
>>> d = Computed(lambda ctx: 7)
>>> d.parse(b"")
7
>>> import os
>>> d = Computed(lambda ctx: os.urandom(10))
>>> d.parse(b"")
b'\x98\xc2\xec\x10\x07\xf5\x8e\x98\xc2\xec'
class construct.core.Const(value, subcon=None)

Field enforcing a constant. It is used for file signatures, to validate that the given pattern exists. Data in the stream must strictly match the specified value.

Note that a variable sized subcon may still provide positive verification. Const does not consume a precomputed amount of bytes, but depends on the subcon to read the appropriate amount (eg. VarInt is acceptable). Whatever subcon parses into, gets compared against the specified value.

Parses using subcon and return its value (after checking). Builds using subcon from nothing (or given object, if not None). Size is the same as subcon, unless it raises SizeofError.

Parameters:
  • value – expected value, usually a bytes literal
  • subcon – optional, Construct instance, subcon used to build value from, assumed to be Bytes if value parameter was a bytes literal
Raises:
  • StreamError – requested reading negative amount, could not read enough bytes, requested writing different amount than actual data, or could not write all bytes
  • ConstError – parsed data does not match specified value, or building from wrong value
  • StringError – building from non-bytes value, perhaps unicode

Example:

>>> d = Const(b"IHDR")
>>> d.build(None)
b'IHDR'
>>> d.parse(b"JPEG")
construct.core.ConstError: expected b'IHDR' but parsed b'JPEG'

>>> d = Const(255, Int32ul)
>>> d.build(None)
b'\xff\x00\x00\x00'
exception construct.core.ConstError
class construct.core.Construct

The mother of all constructs.

This object is generally not directly instantiated, and it does not directly implement parsing and building, so it is largely only of interest to subclass implementors. There are also other abstract classes sitting on top of this one.

The external user API:

  • parse
  • parse_stream
  • parse_file
  • build
  • build_stream
  • build_file
  • sizeof
  • compile
  • benchmark

Subclass authors should not override the external methods. Instead, another API is available:

  • _parse
  • _build
  • _sizeof
  • _actualsize
  • _emitparse
  • _emitbuild
  • __getstate__
  • __setstate__

Attributes and Inheritance:

All constructs have a name and flags. The name is used for naming struct members and context dictionaries. Note that the name can be a string, or None by default. A single underscore “_” is a reserved name, used as up-level in nested containers. The name should be descriptive, short, and valid as a Python identifier, although these rules are not enforced. The flags specify additional behavioral information about this construct. Flags are used by enclosing constructs to determine a proper course of action. Flags are often inherited from inner subconstructs but that depends on each class.

benchmark(sampledata, filename=None)

Measures performance of your construct (its parsing and building runtime), both for the original instance and the compiled instance. Uses timeit module, over at min 1 sample, and at max over 1 second time.

Optionally, results are saved to a text file for later inspection. Otherwise you can print the result string to terminal.

Also this method checks correctness, by comparing parsing/building results from both instances.

Parameters:
  • sampledata – bytes, a valid blob parsable by this construct
  • filename – optional, string, source is saved to that file
Returns:

string containing measurements

build(obj, **contextkw)

Build an object in memory (a bytes object).

Whenever data cannot be written, ConstructError or its derivative is raised. This method is NOT ALLOWED to raise any other exceptions although (1) user-defined lambdas can raise arbitrary exceptions which are propagated (2) external libraries like numpy can raise arbitrary exceptions which are propagated (3) some list and dict lookups can raise IndexError and KeyError which are propagated.

Context entries are passed only as keyword parameters **contextkw.

Parameters:**contextkw – context entries, usually empty
Returns:bytes
Raises:ConstructError – raised for any reason
build_file(obj, filename, **contextkw)

Build an object into a closed binary file. See build().

build_stream(obj, stream, **contextkw)

Build an object directly into a stream. See build().

compile(filename=None)

Transforms a construct into another construct that does same thing (has same parsing and building semantics) but is much faster when parsing. Already compiled instances just compile into itself.

Optionally, partial source code can be saved to a text file. This is meant only to inspect the generated code, not to import it from external scripts.

Returns:Compiled instance
parse(data, **contextkw)

Parse an in-memory buffer (often bytes object). Strings, buffers, memoryviews, and other complete buffers can be parsed with this method.

Whenever data cannot be read, ConstructError or its derivative is raised. This method is NOT ALLOWED to raise any other exceptions although (1) user-defined lambdas can raise arbitrary exceptions which are propagated (2) external libraries like numpy can raise arbitrary exceptions which are propagated (3) some list and dict lookups can raise IndexError and KeyError which are propagated.

Context entries are passed only as keyword parameters **contextkw.

Parameters:**contextkw – context entries, usually empty
Returns:some value, usually based on bytes read from the stream but sometimes it is computed from nothing or from the context dictionary, sometimes its non-deterministic
Raises:ConstructError – raised for any reason
parse_file(filename, **contextkw)

Parse a closed binary file. See parse().

parse_stream(stream, **contextkw)

Parse a stream. Files, pipes, sockets, and other streaming sources of data are handled by this method. See parse().

sizeof(**contextkw)

Calculate the size of this object, optionally using a context.

Some constructs have fixed size (like FormatField), some have variable-size and can determine their size given a context entry (like Bytes(this.otherfield1)), and some cannot determine their size (like VarInt).

Whenever size cannot be determined, SizeofError is raised. This method is NOT ALLOWED to raise any other exception, even if eg. context dictionary is missing a key, or subcon propagates ConstructError-derivative exception.

Context entries are passed only as keyword parameters **contextkw.

Parameters:**contextkw – context entries, usually empty
Returns:integer if computable, SizeofError otherwise
Raises:SizeofError – size could not be determined in actual context, or is impossible to be determined
exception construct.core.ConstructError
class construct.core.Default(subcon, value)

Field where building does not require a value, because the value gets taken from default. Comes handy when building a Struct from a dict with missing keys.

Parsing defers to subcon. Building is defered to subcon, but it builds from a default (if given object is None) or from given object. Building does not require a value, but can accept one. Size is the same as subcon, unless it raises SizeofError.

Difference between Default and Rebuild, is that in first the build value is optional and in second the build value is ignored.

Parameters:
  • subcon – Construct instance
  • value – context lambda or constant value
Raises:

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

Can propagate any exception from the lambda, possibly non-ConstructError.

Example:

>>> d = Struct(
...     "a" / Default(Byte, 0),
... )
>>> d.build(dict(a=1))
b'\x01'
>>> d.build(dict())
b'\x00'
class construct.core.Embedded(subcon)

Special wrapper that allows outer multiple-subcons construct to merge fields from another multiple-subcons construct. Embedded does not change a field, only wraps it like a candy with a flag.

Warning

Can only be used between Struct Sequence FocusedSeq Union LazyStruct, although they can be used interchangably, for example Struct can embed fields from a Sequence. There is also EmbeddedSwitch macro that pseudo-embeds a Switch. Its not possible to embed IfThenElse.

Parsing building and sizeof are deferred to subcon.

Parameters:subcon – Construct instance, its fields to embed inside a struct or sequence

Example:

>>> outer = Struct(
...     Embedded(Struct(
...         "data" / Bytes(4),
...     )),
... )
>>> outer.parse(b"1234")
Container(data=b'1234')
construct.core.EmbeddedSwitch(merged, selector, mapping)

Macro that simulates embedding Switch, which under new embedding semantics is not possible. This macro does NOT produce a Switch. It generates classes that behave the same way as you would expect from embedded Switch, only that. Instance created by this macro CAN be embedded.

Both merged and all values in mapping must be Struct instances. Macro re-creates a single struct that contains all fields, where each field is wrapped in If(selector == key, …). Note that resulting dictionary contains None values for fields that would not be chosen by switch. Note also that if selector does not match any cases, it passes successfully (default Switch behavior).

All fields should have unique names. Otherwise fields that were not selected during parsing may return None and override other fields context entries that have same name. This is because If field returns None value if condition is not met, but the Struct inserts that None value into the context entry regardless.

Parameters:
  • merged – Struct instance
  • selector – this expression, that references one of merged fields
  • mapping – dict with values being Struct instances

Example:

d = EmbeddedSwitch(
    Struct(
        "type" / Byte,
    ),
    this.type,
    {
        0: Struct("name" / PascalString(Byte, "utf8")),
        1: Struct("value" / Byte),
    }
)

# generates essentially following
d = Struct(
    "type" / Byte,
    "name" / If(this.type == 0, PascalString(Byte, "utf8")),
    "value" / If(this.type == 1, Byte),
)

# both parse like following
>>> d.parse(b"\x00\x00")
Container(type=0, name=u'', value=None)
>>> d.parse(b"\x01\x00")
Container(type=1, name=None, value=0)
class construct.core.Enum(subcon, *merge, **mapping)

Translates unicode label names to subcon values, and vice versa.

Parses integer subcon, then uses that value to lookup mapping dictionary. Returns an integer-convertible string (if mapping found) or an integer (otherwise). Building is a reversed process. Can build from an integer flag or string label. Size is same as subcon, unless it raises SizeofError.

There is no default parameter, because if no mapping is found, it parses into an integer without error.

This class supports enum34 module. See examples.

This class supports exposing member labels as attributes, as integer-convertible strings. See examples.

Parameters:
  • subcon – Construct instance, subcon to map to/from
  • *merge – optional, list of enum.IntEnum and enum.IntFlag instances, to merge labels and values from
  • **mapping – dict, mapping string names to values
Raises:

MappingError – building from string but no mapping found

Example:

>>> d = Enum(Byte, one=1, two=2, four=4, eight=8)
>>> d.parse(b"\x01")
'one'
>>> int(d.parse(b"\x01"))
1
>>> d.parse(b"\xff")
255
>>> int(d.parse(b"\xff"))
255

>>> d.build(d.one or "one" or 1)
b'\x01'
>>> d.one
'one'

import enum
class E(enum.IntEnum or enum.IntFlag):
    one = 1
    two = 2

Enum(Byte, E) <--> Enum(Byte, one=1, two=2)
FlagsEnum(Byte, E) <--> FlagsEnum(Byte, one=1, two=2)
class construct.core.EnumInteger

Used internally.

class construct.core.EnumIntegerString

Used internally.

exception construct.core.ExplicitError
class construct.core.ExprAdapter(subcon, decoder, encoder)

Generic adapter that takes decoder and encoder lambdas as parameters. You can use ExprAdapter instead of writing a full-blown class deriving from Adapter when only a simple lambda is needed.

Parameters:
  • subcon – Construct instance, subcon to adapt
  • decoder – lambda that takes (obj, context) and returns an decoded version of obj
  • encoder – lambda that takes (obj, context) and returns an encoded version of obj

Example:

>>> d = ExprAdapter(Byte, obj_+1, obj_-1)
>>> d.parse(b'\x04')
5
>>> d.build(5)
b'\x04'
class construct.core.ExprSymmetricAdapter(subcon, encoder)

Macro around ExprAdapter.

Parameters:
  • subcon – Construct instance, subcon to adapt
  • encoder – lambda that takes (obj, context) and returns both encoded version and decoded version of obj

Example:

>>> d = ExprSymmetricAdapter(Byte, obj_ & 0b00001111)
>>> d.parse(b"ÿ")
15
>>> d.build(255)
b''
class construct.core.ExprValidator(subcon, validator)

Generic adapter that takes validator lambda as parameter. You can use ExprValidator instead of writing a full-blown class deriving from Validator when only a simple lambda is needed.

Parameters:
  • subcon – Construct instance, subcon to adapt
  • validator – lambda that takes (obj, context) and returns a bool

Example:

>>> d = ExprValidator(Byte, obj_ & 0b11111110 == 0)
>>> d.build(1)
b'\x01'
>>> d.build(88)
ValidationError: object failed validation: 88
construct.core.Filter(predicate, subcon)

Filters a list leaving only the elements that passed through the predicate.

Parameters:
  • subcon – Construct instance, usually Array GreedyRange Sequence
  • predicate – lambda that takes (obj, context) and returns a bool

Can propagate any exception from the lambda, possibly non-ConstructError.

Example:

>>> d = Filter(obj_ != 0, Byte[:])
>>> d.parse(b"\x00\x02\x00")
[2]
>>> d.build([0,1,0,2,0])
b'\x01\x02'
class construct.core.FixedSized(length, subcon)

Restricts parsing to specified amount of bytes.

Parsing reads length bytes, then defers to subcon using new BytesIO with said bytes. Building builds the subcon using new BytesIO, then writes said data and additional null bytes accordingly. Size is same as length, although negative amount raises an error as well.

Parameters:
  • length – integer or context lambda, total amount of bytes (both data and padding)
  • subcon – Construct instance
Raises:
  • StreamError – requested reading negative amount, could not read enough bytes, requested writing different amount than actual data, or could not write all bytes
  • PaddingError – length is negative
  • PaddingError – subcon written more bytes than entire length (negative padding)

Can propagate any exception from the lambda, possibly non-ConstructError.

Example:

>>> d = FixedSized(10, Byte)
>>> d.parse(b'\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00')
255
>>> d.build(255)
b'\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00'
>>> d.sizeof()
10
class construct.core.FlagsEnum(subcon, *merge, **flags)

Translates unicode label names to subcon integer (sub)values, and vice versa.

Parses integer subcon, then creates a Container, where flags define each key. Builds from a container by bitwise-oring of each flag if it matches a set key. Can build from an integer flag or string label directly, as well as | concatenations thereof (see examples). Size is same as subcon, unless it raises SizeofError.

This class supports enum34 module. See examples.

This class supports exposing member labels as attributes, as bitwisable strings. See examples.

Parameters:
  • subcon – Construct instance, must operate on integers
  • *merge – optional, list of enum.IntEnum and enum.IntFlag instances, to merge labels and values from
  • **flags – dict, mapping string names to integer values
Raises:
  • MappingError – building from object not like: integer string dict
  • MappingError – building from string but no mapping found

Can raise arbitrary exceptions when computing | and & and value is non-integer.

Example:

>>> d = FlagsEnum(Byte, one=1, two=2, four=4, eight=8)
>>> d.parse(b"\x03")
Container(one=True, two=True, four=False, eight=False)
>>> d.build(dict(one=True,two=True))
b'\x03'

>>> d.build(d.one|d.two or "one|two" or 1|2)
b'\x03'

import enum
class E(enum.IntEnum or enum.IntFlag):
    one = 1
    two = 2

Enum(Byte, E) <--> Enum(Byte, one=1, two=2)
FlagsEnum(Byte, E) <--> FlagsEnum(Byte, one=1, two=2)
class construct.core.FocusedSeq(parsebuildfrom, *subcons, **subconskw)

Allows constructing more elaborate “adapters” than Adapter class.

Parse does parse all subcons in sequence, but returns only the element that was selected (discards other values). Build does build all subcons in sequence, where each gets build from nothing (except the selected subcon which is given the object). 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 supports embedding. Embedded semantics dictate, that during instance creation (in ctor), each field is checked for embedded flag, and its subcon members are merged. This changes behavior of some code examples. Only few classes are supported: Struct Sequence FocusedSeq Union LazyStruct, although those can be used interchangably (a Struct can embed a Sequence, or rather its members).

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 is used internally to implement PrefixedArray.

Parameters:
  • parsebuildfrom – string name or context lambda, selects a subcon
  • *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
  • UnboundLocalError – selector does not match any subcon

Can propagate any exception from the lambda, possibly non-ConstructError.

Excample:

>>> d = FocusedSeq("num", Const(b"SIG"), "num"/Byte, Terminated)
>>> d.parse(b"SIG\xff")
255
>>> d.build(255)
b'SIG\xff'

>>> d = FocusedSeq("animal",
...     "animal" / Enum(Byte, giraffe=1),
... )
>>> d.animal.giraffe
'giraffe'
>>> d = FocusedSeq("count",
...     "count" / Byte,
...     "data" / Padding(lambda this: this.count - this._subcons.count.sizeof()),
... )
>>> d.build(4)
b'\x04\x00\x00\x00'

PrefixedArray <--> FocusedSeq("items",
    "count" / Rebuild(lengthfield, len_(this.items)),
    "items" / subcon[this.count],
)
class construct.core.FormatField(endianity, format)

Field that uses struct module to pack and unpack CPU-sized integers and floats. This is used to implement most Int* Float* fields, but for example cannot pack 24-bit integers, which is left to BytesInteger class.

See struct module documentation for instructions on crafting format strings.

Parses into an integer. Builds from an integer into specified byte count and endianness. Size is determined by struct module according to specified format string.

Parameters:
  • endianity – string, character like: < > =
  • format – string, character like: f d B H L Q b h l q
Raises:
  • StreamError – requested reading negative amount, could not read enough bytes, requested writing different amount than actual data, or could not write all bytes
  • FormatFieldError – wrong format string, or struct.(un)pack complained about the value

Example:

>>> d = FormatField(">", "H") or Int16ub
>>> d.parse(b"\x01\x00")
256
>>> d.build(256)
b"\x01\x00"
>>> d.sizeof()
2
exception construct.core.FormatFieldError
class construct.core.GreedyRange(subcon, discard=False)

Homogenous array of elements, similar to C# generic IEnumerable<T>, but works with unknown count of elements by parsing until end of stream.

Parses into a ListContainer (a list). Parsing stops when an exception occured when parsing the subcon, either due to EOF or subcon format not being able to parse the data. Either way, when GreedyRange encounters either failure it seeks the stream back to a position after last successful subcon parsing. Builds from enumerable, each element as-is. Size is undefined.

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:
  • subcon – Construct instance, subcon to process individual elements
  • discard – optional, bool, if set then parsing returns empty list
Raises:
  • StreamError – requested reading negative amount, could not read enough bytes, requested writing different amount than actual data, or could not write all bytes
  • StreamError – stream is not seekable and tellable

Can propagate any exception from the lambdas, possibly non-ConstructError.

Example:

>>> d = GreedyRange(Byte)
>>> d.build(range(8))
b'\x00\x01\x02\x03\x04\x05\x06\x07'
>>> d.parse(_)
[0, 1, 2, 3, 4, 5, 6, 7]
construct.core.GreedyString(encoding)

String that reads entire stream until EOF, and writes a given string as-is. Analog to GreedyBytes but also applies unicode-to-bytes encoding.

Parameters:

encoding – string like: utf8 utf16 utf32 ascii

Raises:

Example:

>>> d = GreedyString("utf8")
>>> d.build(u"Афон")
b'\xd0\x90\xd1\x84\xd0\xbe\xd0\xbd'
>>> d.parse(_)
u'Афон'
class construct.core.Hex(subcon)

Adapter for displaying hexadecimal/hexlified representation of integers/bytes/RawCopy dictionaries.

Parsing results in int-alike bytes-alike or dict-alike object, whose only difference from original is pretty-printing. If you look at the result, you will be presented with its repr which remains as-is. If you print it, then you will see its str whic is a hexlified representation. Building and sizeof defer to subcon.

To obtain a hexlified string (like before Hex HexDump changed semantics) use binascii.(un)hexlify on parsed results.

Example:

>>> d = Hex(Int32ub)
>>> obj = d.parse(b"\x00\x00\x01\x02")
>>> obj
258
>>> print(obj)
0x00000102

>>> d = Hex(GreedyBytes)
>>> obj = d.parse(b"\x00\x00\x01\x02")
>>> obj
b'\x00\x00\x01\x02'
>>> print(obj)
unhexlify('00000102')

>>> d = Hex(RawCopy(Int32ub))
>>> obj = d.parse(b"\x00\x00\x01\x02")
>>> obj
{'data': b'\x00\x00\x01\x02',
 'length': 4,
 'offset1': 0,
 'offset2': 4,
 'value': 258}
>>> print(obj)
unhexlify('00000102')
class construct.core.HexDump(subcon)

Adapter for displaying hexlified representation of bytes/RawCopy dictionaries.

Parsing results in bytes-alike or dict-alike object, whose only difference from original is pretty-printing. If you look at the result, you will be presented with its repr which remains as-is. If you print it, then you will see its str whic is a hexlified representation. Building and sizeof defer to subcon.

To obtain a hexlified string (like before Hex HexDump changed semantics) use construct.lib.hexdump on parsed results.

Example:

>>> d = HexDump(GreedyBytes)
>>> obj = d.parse(b"\x00\x00\x01\x02")
>>> obj
b'\x00\x00\x01\x02'
>>> print(obj)
hexundump('''
0000   00 00 01 02                                       ....
''')

>>> d = HexDump(RawCopy(Int32ub))
>>> obj = d.parse(b"\x00\x00\x01\x02")
>>> obj
{'data': b'\x00\x00\x01\x02',
 'length': 4,
 'offset1': 0,
 'offset2': 4,
 'value': 258}
>>> print(obj)
hexundump('''
0000   00 00 01 02                                       ....
''')
construct.core.If(condfunc, subcon)

If-then conditional construct.

Parsing evaluates condition, if True then subcon is parsed, otherwise just returns None. Building also evaluates condition, if True then subcon gets build from, otherwise does nothing. Size is either same as subcon or 0, depending how condfunc evaluates.

Parameters:
  • condfunc – bool or context lambda (or a truthy value)
  • subcon – Construct instance, used if condition indicates True
Raises:

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

Can propagate any exception from the lambda, possibly non-ConstructError.

Example:

If <--> IfThenElse(condfunc, subcon, Pass)

>>> d = If(this.x > 0, Byte)
>>> d.build(255, x=1)
b'\xff'
>>> d.build(255, x=0)
b''
class construct.core.IfThenElse(condfunc, thensubcon, elsesubcon)

If-then-else conditional construct, similar to ternary operator.

Parsing and building evaluates condition, and defers to either subcon depending on the value. Size is computed the same way.

Parameters:
  • condfunc – bool or context lambda (or a truthy value)
  • thensubcon – Construct instance, used if condition indicates True
  • elsesubcon – Construct instance, used if condition indicates False
Raises:

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

Can propagate any exception from the lambda, possibly non-ConstructError.

Example:

>>> d = IfThenElse(this.x > 0, VarInt, Byte)
>>> d.build(255, dict(x=1))
b'\xff\x01'
>>> d.build(255, dict(x=0))
b'\xff'
exception construct.core.IndexFieldError
class construct.core.Indexing(subcon, count, index, empty=None)

Adapter for indexing a list (getting a single item from that list). Works with Range and Sequence and their lazy equivalents.

Parameters:
  • subcon – Construct instance, subcon to index
  • count – integer, expected number of elements, needed during building
  • index – integer, index of the list to get
  • empty – object, value to fill the list with, during building

Example:

d = Indexing(Array(4,Byte), 4, 2, empty=0)
assert d.parse(b"\x01\x02\x03\x04") == 3
assert d.build(3) == b"\x00\x00\x03\x00"
assert d.sizeof() == 4
exception construct.core.IntegerError
class construct.core.Lazy(subcon)

Lazyfies a field.

This wrapper allows you to do lazy parsing of individual fields inside a normal Struct (without using LazyStruct which may not work in every scenario). It is also used by KaitaiStruct compiler to emit instances because those are not processed greedily, and they may refer to other not yet parsed fields. Those are 2 entirely different applications but semantics are the same.

Parsing saves the current stream offset and returns a lambda. If and when that lambda gets evaluated, it seeks the stream to then-current position, parses the subcon, and seeks the stream back to previous position. Building evaluates that lambda into an object (if needed), then defers to subcon. Size also defers to subcon.

Parameters:

subcon – Construct instance

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

Example:

>>> d = Lazy(Byte)
>>> x = d.parse(b'\x00')
>>> x
<function construct.core.Lazy._parse.<locals>.execute>
>>> x()
0
>>> d.build(0)
b'\x00'
>>> d.build(x)
b'\x00'
>>> d.sizeof()
1
class construct.core.LazyArray(count, subcon)

Equivalent to Array, but the subcon is not parsed when possible (it gets skipped if the size can be measured by _actualsize or _sizeof method). See its docstring for details.

Fields are parsed depending on some factors:

  • Some fields like Int* Float* Bytes(5) Array(5,Byte) Pointer are fixed-size and are therefore skipped. Stream is not read.
  • Some fields like Bytes(this.field) are variable-size but their size is known during parsing when there is a corresponding context entry. Those fields are also skipped. Stream is not read.
  • Some fields like Prefixed PrefixedArray PascalString are variable-size but their size can be computed by partially reading the stream. Only first few bytes are read (the lengthfield).
  • Other fields like VarInt need to be parsed. Stream position that is left after the field was parsed is used.
  • Some fields may not work properly, due to the fact that this class attempts to skip fields, and parses them only out of necessity. Miscellaneous fields often have size defined as 0, and fixed sized fields are skippable.

Note there are restrictions:

  • If a field references another field within inner (nested) or outer (super) struct, things may break. Context is nested, but this class was not rigorously tested in that manner.

Building and sizeof are greedy, like in Array.

Parameters:
  • count – integer or context lambda, strict amount of elements
  • subcon – Construct instance, subcon to process individual elements
class construct.core.LazyBound(subconfunc)

Field that binds to the subcon only at runtime (during parsing and building, not ctor). Useful for recursive data structures, like linked-lists and trees, where a construct needs to refer to itself (while it does not exist yet in the namespace).

Note that it is possible to obtain same effect without using this class, using a loop. However there are usecases where that is not possible (if remaining nodes cannot be sized-up, and there is data following the recursive structure). There is also a significant difference, namely that LazyBound actually does greedy parsing while the loop does lazy parsing. See examples.

To break recursion, use If field. See examples.

Parameters:subconfunc – parameter-less lambda returning Construct instance, can also return itself

Example:

d = Struct(
    "value" / Byte,
    "next" / If(this.value > 0, LazyBound(lambda: d)),
)
>>> print(d.parse(b"\x05\x09\x00"))
Container:
    value = 5
    next = Container:
        value = 9
        next = Container:
            value = 0
            next = None
d = Struct(
    "value" / Byte,
    "next" / GreedyBytes,
)
data = b"\x05\x09\x00"
while data:
    x = d.parse(data)
    data = x.next
    print(x)
# print outputs
Container:
    value = 5
    next = \t\x00 (total 2)
# print outputs
Container:
    value = 9
    next = \x00 (total 1)
# print outputs
Container:
    value = 0
    next =  (total 0)
class construct.core.LazyContainer(struct, stream, offsets, values, context, path)

Used internally.

items() → list of D's (key, value) pairs, as 2-tuples
keys() → list of D's keys
values() → list of D's values
class construct.core.LazyListContainer(subcon, stream, count, offsets, values, context, path)

Used internally.

class construct.core.LazyStruct(*subcons, **subconskw)

Equivalent to Struct, but when this class is parsed, most fields are not parsed (they are skipped if their size can be measured by _actualsize or _sizeof method). See its docstring for details.

Fields are parsed depending on some factors:

  • Some fields like Int* Float* Bytes(5) Array(5,Byte) Pointer are fixed-size and are therefore skipped. Stream is not read.
  • Some fields like Bytes(this.field) are variable-size but their size is known during parsing when there is a corresponding context entry. Those fields are also skipped. Stream is not read.
  • Some fields like Prefixed PrefixedArray PascalString are variable-size but their size can be computed by partially reading the stream. Only first few bytes are read (the lengthfield).
  • Other fields like VarInt need to be parsed. Stream position that is left after the field was parsed is used.
  • Some fields may not work properly, due to the fact that this class attempts to skip fields, and parses them only out of necessity. Miscellaneous fields often have size defined as 0, and fixed sized fields are skippable.

Note there are restrictions:

  • If a field like Bytes(this.field) references another field in the same struct, you need to access the referenced field first (to trigger its parsing) and then you can access the Bytes field. Otherwise it would fail due to missing context entry.
  • If a field references another field within inner (nested) or outer (super) struct, things may break. Context is nested, but this class was not rigorously tested in that manner.

Building and sizeof are greedy, like in Struct.

Parameters:
  • *subcons – Construct instances, list of members, some can be anonymous
  • **subconskw – Construct instances, list of members (requires Python 3.6)
class construct.core.Mapping(subcon, mapping)

Adapter that maps objects to other objects. Translates objects after parsing and before building. Can for example, be used to translate between enum34 objects and strings, but Enum class supports enum34 already and is recommended.

Parameters:
  • subcon – Construct instance
  • mapping – dict, for encoding (building) mapping, the reversed is used for parsing mapping
Raises:

MappingError – parsing or building but no mapping found

Example:

>>> x = object
>>> d = Mapping(Byte, {x:0})
>>> d.parse(b"\x00")
x
>>> d.build(x)
b'\x00'
exception construct.core.MappingError
class construct.core.NamedTuple(tuplename, tuplefields, subcon)

Both arrays, structs, and sequences can be mapped to a namedtuple from collections module. To create a named tuple, you need to provide a name and a sequence of fields, either a string with space-separated names or a list of string names, like the standard namedtuple.

Parses into a collections.namedtuple instance, and builds from such instance (although it also builds from lists and dicts). Size is undefined.

Parameters:
  • tuplename – string
  • tuplefields – string or list of strings
  • subcon – Construct instance, either Struct Sequence Array GreedyRange
Raises:
  • StreamError – requested reading negative amount, could not read enough bytes, requested writing different amount than actual data, or could not write all bytes
  • NamedTupleError – subcon is neither Struct Sequence Array GreedyRange

Can propagate collections exceptions.

Example:

>>> d = NamedTuple("coord", "x y z", Byte[3])
>>> d = NamedTuple("coord", "x y z", Byte >> Byte >> Byte)
>>> d = NamedTuple("coord", "x y z", "x"/Byte + "y"/Byte + "z"/Byte)
>>> d.parse(b"123")
coord(x=49, y=50, z=51)
exception construct.core.NamedTupleError
construct.core.NoneOf(subcon, invalids)

Validates that the object is none of the listed values, both during parsing and building.

Note

For performance, valids should be a set/frozenset.

Parameters:
  • subcon – Construct instance, subcon to validate
  • invalids – collection implementing __contains__, usually a list or set
Raises:

ValidationError – parsed or build value is among invalids

class construct.core.NullStripped(subcon, pad='x00')

Restricts parsing to bytes except padding left of EOF.

Parsing reads entire stream, then strips the data from right to left of null bytes, then parses subcon using new BytesIO made of said data. Building defers to subcon as-is. Size is undefined, because it reads till EOF.

The pad can be multiple bytes, to support string classes with UTF16/32 encodings.

Parameters:
  • subcon – Construct instance
  • pad – optional, bytes, padding byte-string, default is x00 single null byte
Raises:

PaddingError – pad is less than 1 bytes in length

Example:

>>> d = NullStripped(Byte)
>>> d.parse(b'\xff\x00\x00')
255
>>> d.build(255)
b'\xff'
class construct.core.NullTerminated(subcon, term='x00', include=False, consume=True, require=True)

Restricts parsing to bytes preceding a null byte.

Parsing reads one byte at a time and accumulates it with previous bytes. When term was found, (by default) consumes but discards the term. When EOF was found, (by default) raises same StreamError exception. Then subcon is parsed using new BytesIO made with said data. Building builds the subcon and then writes the term. Size is undefined.

The term can be multiple bytes, to support string classes with UTF16/32 encodings.

Parameters:
  • subcon – Construct instance
  • term – optional, bytes, terminator byte-string, default is x00 single null byte
  • include – optional, bool, if to include terminator in resulting data, default is False
  • consume – optional, bool, if to consume terminator or leave it in the stream, default is True
  • require – optional, bool, if EOF results in failure or not, default is True
Raises:
  • StreamError – requested reading negative amount, could not read enough bytes, requested writing different amount than actual data, or could not write all bytes
  • StreamError – encountered EOF but require is not disabled
  • PaddingError – terminator is less than 1 bytes in length

Example:

>>> d = NullTerminated(Byte)
>>> d.parse(b'\xff\x00')
255
>>> d.build(255)
b'\xff\x00'
construct.core.OneOf(subcon, valids)

Validates that the object is one of the listed values, both during parsing and building.

Note

For performance, valids should be a set/frozenset.

Parameters:
  • subcon – Construct instance, subcon to validate
  • valids – collection implementing __contains__, usually a list or set
Raises:

ValidationError – parsed or build value is not among valids

Example:

>>> d = OneOf(Byte, [1,2,3])
>>> d.parse(b"\x01")
1
>>> d.parse(b"\xff")
construct.core.ValidationError: object failed validation: 255
construct.core.Optional(subcon)

Makes an optional field.

Parsing attempts to parse subcon. If sub-parsing fails, returns None and reports success. Building attempts to build subcon. If sub-building fails, writes nothing and reports success. Size is undefined, because whether bytes would be consumed or produced depends on actual data and actual context.

Parameters:subcon – Construct instance

Example:

Optional  <-->  Select(subcon, Pass)

>>> d = Optional(Int64ul)
>>> d.parse(b"12345678")
4050765991979987505
>>> d.parse(b"")
None
>>> d.build(1)
b'\x01\x00\x00\x00\x00\x00\x00\x00'
>>> d.build(None)
b''
class construct.core.Padded(length, subcon, pattern='x00')

Appends additional null bytes to achieve a length.

Parsing first parses the subcon, then uses stream.tell() to measure how many bytes were read and consumes additional bytes accordingly. Building first builds the subcon, then uses stream.tell() to measure how many bytes were written and produces additional bytes accordingly. Size is same as length, but negative amount results in error. Note that subcon can actually be variable size, it is the eventual amount of bytes that is read or written during parsing or building that determines actual padding.

Parameters:
  • length – integer or context lambda, length of the padding
  • subcon – Construct instance
  • pattern – optional, b-character, padding pattern, default is \x00
Raises:
  • StreamError – requested reading negative amount, could not read enough bytes, requested writing different amount than actual data, or could not write all bytes
  • PaddingError – length is negative
  • PaddingError – subcon read or written more than the length (would cause negative pad)
  • PaddingError – pattern is not bytes of length 1

Can propagate any exception from the lambda, possibly non-ConstructError.

Example:

>>> d = Padded(4, Byte)
>>> d.build(255)
b'\xff\x00\x00\x00'
>>> d.parse(_)
255
>>> d.sizeof()
4

>>> d = Padded(4, VarInt)
>>> d.build(1)
b'\x01\x00\x00\x00'
>>> d.build(70000)
b'\xf0\xa2\x04\x00'
construct.core.PaddedString(length, encoding)

Configurable, fixed-length or variable-length string field.

When parsing, the byte string is stripped of null bytes (per encoding unit), then decoded. Length is an integer or context lambda. When building, the string is encoded and then padded to specified length. If encoded string is larger than the specified length, it fails with PaddingError. Size is same as length parameter.

Warning

PaddedString and CString only support encodings explicitly listed in possiblestringencodings .

Parameters:
  • length – integer or context lambda, length in bytes (not unicode characters)
  • encoding – string like: utf8 utf16 utf32 ascii
Raises:

Can propagate any exception from the lambda, possibly non-ConstructError.

Example:

>>> d = PaddedString(10, "utf8")
>>> d.build(u"Афон")
b'\xd0\x90\xd1\x84\xd0\xbe\xd0\xbd\x00\x00'
>>> d.parse(_)
u'Афон'
construct.core.Padding(length, pattern='\x00')

Appends null bytes.

Parsing consumes specified amount of bytes and discards it. Building writes specified pattern byte multiplied into specified length. Size is same as specified.

Parameters:
  • length – integer or context lambda, length of the padding
  • pattern – b-character, padding pattern, default is \x00
Raises:
  • StreamError – requested reading negative amount, could not read enough bytes, requested writing different amount than actual data, or could not write all bytes
  • PaddingError – length was negative
  • PaddingError – pattern was not bytes (b-character)

Can propagate any exception from the lambda, possibly non-ConstructError.

Example:

>>> d = Padding(4) or Padded(4, Pass)
>>> d.build(None)
b'\x00\x00\x00\x00'
>>> d.parse(b"****")
None
>>> d.sizeof()
4
exception construct.core.PaddingError
construct.core.PascalString(lengthfield, encoding)

Length-prefixed string. The length field can be variable length (such as VarInt) or fixed length (such as Int64ub). VarInt is recommended when designing new protocols. Stored length is in bytes, not characters. Size is not defined.

Parameters:
  • lengthfield – Construct instance, field used to parse and build the length (like VarInt Int64ub)
  • encoding – string like: utf8 utf16 utf32 ascii
Raises:

StringError – building a non-unicode string

Example:

>>> d = PascalString(VarInt, "utf8")
>>> d.build(u"Афон")
b'\x08\xd0\x90\xd1\x84\xd0\xbe\xd0\xbd'
>>> d.parse(_)
u'Афон'
class construct.core.Peek(subcon)

Peeks at the stream.

Parsing sub-parses (and returns None if failed), then reverts stream to original position. Building does nothing (its NOT deferred). Size is defined as 0 because there is no building.

This class is used in Union class to parse each member.

Parameters:

subcon – Construct instance

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

Example:

>>> d = Sequence(Peek(Int8ub), Peek(Int16ub))
>>> d.parse(b"\x01\x02")
[1, 258]
>>> d.sizeof()
0
class construct.core.Pointer(offset, subcon, stream=None)

Jumps in the stream forth and back for one field.

Parsing and building seeks the stream to new location, processes subcon, and seeks back to original location. Size is defined as 0 but that does not mean no bytes are written into the stream.

Offset can be positive, indicating a position from stream beginning forward, or negative, indicating a position from EOF backwards.

Parameters:
  • offset – integer or context lambda, positive or negative
  • subcon – Construct instance
  • stream – None to use original stream (default), or context lambda to provide a different stream
Raises:
  • StreamError – requested reading negative amount, could not read enough bytes, requested writing different amount than actual data, or could not write all bytes
  • StreamError – stream is not seekable and tellable

Can propagate any exception from the lambda, possibly non-ConstructError.

Example:

>>> d = Pointer(8, Bytes(1))
>>> d.parse(b"abcdefghijkl")
b'i'
>>> d.build(b"Z")
b'\x00\x00\x00\x00\x00\x00\x00\x00Z'
class construct.core.Prefixed(lengthfield, subcon, includelength=False)

Prefixes a field with byte count.

Parses the length field. Then reads that amount of bytes, and parses subcon using only those bytes. Constructs that consume entire remaining stream are constrained to consuming only the specified amount of bytes (a substream). When building, data gets prefixed by its length. Optionally, length field can include its own size. Size is the sum of both fields sizes, unless either raises SizeofError.

Analog to PrefixedArray which prefixes with an element count, instead of byte count. Semantics is similar but implementation is different.

VarInt is recommended for new protocols, as it is more compact and never overflows.

Parameters:
  • lengthfield – Construct instance, field used for storing the length
  • subcon – Construct instance, subcon used for storing the value
  • includelength – optional, bool, whether length field should include its own size, default is False
Raises:

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

Example:

>>> d = Prefixed(VarInt, GreedyRange(Int32ul))
>>> d.parse(b"\x08abcdefgh")
[1684234849, 1751606885]

>>> d = PrefixedArray(VarInt, Int32ul)
>>> d.parse(b"\x02abcdefgh")
[1684234849, 1751606885]
construct.core.PrefixedArray(countfield, subcon)

Prefixes an array with item count (as opposed to prefixed by byte count, see Prefixed).

VarInt is recommended for new protocols, as it is more compact and never overflows.

Parameters:
  • countfield – Construct instance, field used for storing the element count
  • subcon – Construct instance, subcon used for storing each element
Raises:
  • StreamError – requested reading negative amount, could not read enough bytes, requested writing different amount than actual data, or could not write all bytes
  • RangeError – consumed or produced too little elements

Example:

>>> d = Prefixed(VarInt, GreedyRange(Int32ul))
>>> d.parse(b"\x08abcdefgh")
[1684234849, 1751606885]

>>> d = PrefixedArray(VarInt, Int32ul)
>>> d.parse(b"\x02abcdefgh")
[1684234849, 1751606885]
class construct.core.ProcessRotateLeft(amount, group, subcon)

Transforms bytes between the underlying stream and the subcon.

Used internally by KaitaiStruct compiler, when translating process: rol/ror tags.

Parsing reads till EOF, rotates (shifts) the data left by amount in bits, then feeds that data into subcon. Building first builds the subcon into separate BytesIO stream, rotates right by negating amount, then writes that data into the main stream. Size is the same as subcon, unless it raises SizeofError.

Parameters:
  • amount – integer or context lambda, shift by this amount in bits, treated modulo (group x 8)
  • group – integer or context lambda, shifting is applied to chunks of this size in bytes
  • subcon – Construct instance
Raises:

Can propagate any exception from the lambda, possibly non-ConstructError.

Example:

>>> d = ProcessRotateLeft(4, 1, Int16ub)
>>> d.parse(b'\x0f\xf0')
0xf00f
>>> d = ProcessRotateLeft(4, 2, Int16ub)
>>> d.parse(b'\x0f\xf0')
0xff00
>>> d.sizeof()
2
class construct.core.ProcessXor(padfunc, subcon)

Transforms bytes between the underlying stream and the subcon.

Used internally by KaitaiStruct compiler, when translating process: xor tags.

Parsing reads till EOF, xors data with the pad, then feeds that data into subcon. Building first builds the subcon into separate BytesIO stream, xors data with the pad, then writes that data into the main stream. Size is the same as subcon, unless it raises SizeofError.

Parameters:
  • padfunc – integer or bytes or context lambda, single or multiple bytes to xor data with
  • subcon – Construct instance
Raises:

StringError – pad is not integer or bytes

Can propagate any exception from the lambda, possibly non-ConstructError.

Example:

>>> d = ProcessXor(0xf0 or b'\xf0', Int16ub)
>>> d.parse(b"\x00\xff")
0xf00f
>>> d.sizeof()
2
exception construct.core.RangeError
class construct.core.RawCopy(subcon)

Used to obtain byte representation of a field (aside of object value).

Returns a dict containing both parsed subcon value, the raw bytes that were consumed by subcon, starting and ending offset in the stream, and amount in bytes. Builds either from raw bytes representation or a value used by subcon. Size is same as subcon.

Object is a dictionary with either “data” or “value” keys, or both.

Parameters:

subcon – Construct instance

Raises:
  • StreamError – stream is not seekable and tellable
  • RawCopyError – building and neither data or value was given
  • StringError – building from non-bytes value, perhaps unicode

Example:

>>> d = RawCopy(Byte)
>>> d.parse(b"\xff")
Container(data=b'\xff')(value=255)(offset1=0)(offset2=1)(length=1)
>>> d.build(dict(data=b"\xff"))
'\xff'
>>> d.build(dict(value=255))
'\xff'
exception construct.core.RawCopyError
class construct.core.Rebuffered(subcon, tailcutoff=None)

Caches bytes from underlying stream, so it becomes seekable and tellable, and also becomes blocking on reading. Useful for processing non-file streams like pipes, sockets, etc.

Warning

Experimental implementation. May not be mature enough.

Parameters:
  • subcon – Construct instance, subcon which will operate on the buffered stream
  • tailcutoff – optional, integer, amount of bytes kept in buffer, by default buffers everything

Can also raise arbitrary exceptions in its implementation.

Example:

Rebuffered(..., tailcutoff=1024).parse_stream(nonseekable_stream)
class construct.core.Rebuild(subcon, func)

Field where building does not require a value, because the value gets recomputed when needed. Comes handy when building a Struct from a dict with missing keys. Useful for length and count fields when Prefixed and PrefixedArray cannot be used.

Parsing defers to subcon. Building is defered to subcon, but it builds from a value provided by the context lambda (or constant). Size is the same as subcon, unless it raises SizeofError.

Difference between Default and Rebuild, is that in first the build value is optional and in second the build value is ignored.

Parameters:
  • subcon – Construct instance
  • func – context lambda or constant value
Raises:

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

Can propagate any exception from the lambda, possibly non-ConstructError.

Example:

>>> d = Struct(
...     "count" / Rebuild(Byte, len_(this.items)),
...     "items" / Byte[this.count],
... )
>>> d.build(dict(items=[1,2,3]))
b'\x03\x01\x02\x03'
class construct.core.Renamed(subcon, newname=None, newdocs=None, newparsed=None)

Special wrapper that allows a Struct (or other similar class) to see a field as having a name (or a different name) or having a parsed hook. Library classes do not have names (its None). Renamed does not change a field, only wraps it like a candy with a label. Used internally by / and * operators.

Also this wrapper is responsible for building a path info (a chain of names) that gets attached to error message when parsing, building, or sizeof fails. Fields that are not named do not appear in the path string.

Parsing building and size are deferred to subcon.

Parameters:
  • subcon – Construct instance
  • newname – optional, string
  • newdocs – optional, string
  • newparsed – optional, lambda

Example:

>>> "number" / Int32ub
<Renamed: number>
exception construct.core.RepeatError
class construct.core.RepeatUntil(predicate, subcon, discard=False)

Homogenous array of elements, similar to C# generic IEnumerable<T>, that repeats until the predicate indicates it to stop. Note that the last element (that predicate indicated as True) is included in the return list.

Parse iterates indefinately until last element passed the predicate. Build iterates indefinately over given list, until an element passed the precicate (or raises RepeatError if no element passed it). Size is undefined.

Parameters:
  • predicate – lambda that takes (obj, list, context) and returns True to break or False to continue (or a truthy value)
  • subcon – Construct instance, subcon used to parse and build each element
  • discard – optional, bool, if set then parsing returns empty list
Raises:
  • StreamError – requested reading negative amount, could not read enough bytes, requested writing different amount than actual data, or could not write all bytes
  • RepeatError – consumed all elements in the stream but neither passed the predicate

Can propagate any exception from the lambda, possibly non-ConstructError.

Example:

>>> d = RepeatUntil(lambda x,lst,ctx: x > 7, Byte)
>>> d.build(range(20))
b'\x00\x01\x02\x03\x04\x05\x06\x07\x08'
>>> d.parse(b"\x01\xff\x02")
[1, 255]

>>> d = RepeatUntil(lambda x,lst,ctx: lst[-2:] == [0,0], Byte)
>>> d.parse(b"\x01\x00\x00\xff")
[1, 0, 0]
class construct.core.RestreamData(datafunc, subcon)

Parses a field on external data (but does not build).

Parsing defers to subcon, but provides it a separate BytesIO stream based on data provided by datafunc (a bytes literal or another BytesIO stream or Construct instances that returns bytes or context lambda). Building does nothing. Size is 0 because as far as other fields see it, this field does not produce or consume any bytes from the stream.

Parameters:
  • datafunc – bytes or BytesIO or Construct instance (that parses into bytes) or context lambda, provides data for subcon to parse from
  • subcon – Construct instance

Can propagate any exception from the lambdas, possibly non-ConstructError.

Example:

>>> d = RestreamData(b"\x01", Int8ub)
>>> d.parse(b"")
1
>>> d.build(0)
b''

>>> d = RestreamData(NullTerminated(GreedyBytes), Int16ub)
>>> d.parse(b"\x01\x02\x00")
0x0102
>>> d = RestreamData(FixedSized(2, GreedyBytes), Int16ub)
>>> d.parse(b"\x01\x02\x00")
0x0102
class construct.core.Restreamed(subcon, decoder, decoderunit, encoder, encoderunit, sizecomputer)

Transforms bytes between the underlying stream and the (variable-sized) subcon.

Used internally to implement Bitwise Bytewise ByteSwapped BitsSwapped .

Warning

Remember that subcon must consume or produce an amount of bytes that is a multiple of encoding or decoding units. For example, in a Bitwise context you should process a multiple of 8 bits or the stream will fail during parsing/building.

Warning

Do NOT use seeking/telling classes inside Restreamed context.

Parameters:
  • subcon – Construct instance
  • decoder – bytes-to-bytes function, used on data chunks when parsing
  • decoderunit – integer, decoder takes chunks of this size
  • encoder – bytes-to-bytes function, used on data chunks when building
  • encoderunit – integer, encoder takes chunks of this size
  • sizecomputer – function that computes amount of bytes outputed

Can propagate any exception from the lambda, possibly non-ConstructError. Can also raise arbitrary exceptions in RestreamedBytesIO implementation.

Example:

Bitwise  <--> Restreamed(subcon, bits2bytes, 8, bytes2bits, 1, lambda n: n//8)
Bytewise <--> Restreamed(subcon, bytes2bits, 1, bits2bytes, 8, lambda n: n*8)
exception construct.core.RotationError
class construct.core.Seek(at, whence=0)

Seeks the stream.

Parsing and building seek the stream to given location (and whence), and return stream.seek() return value. Size is not defined.

See also

Analog Pointer wrapper that has same side effect but also processes a subcon, and also seeks back.

Parameters:
  • at – integer or context lambda, where to jump to
  • whence – optional, integer or context lambda, is the offset from beginning (0) or from current position (1) or from EOF (2), default is 0
Raises:

StreamError – stream is not seekable

Can propagate any exception from the lambda, possibly non-ConstructError.

Example:

>>> d = (Seek(5) >> Byte)
>>> d.parse(b"01234x")
[5, 120]

>>> d = (Bytes(10) >> Seek(5) >> Byte)
>>> d.build([b"0123456789", None, 255])
b'01234\xff6789'
class construct.core.Select(*subcons, **subconskw)

Selects the first matching subconstruct.

Parses and builds by literally trying each subcon in sequence until one of them parses or builds without exception. Stream gets reverted back to original position after each failed attempt, but not if parsing succeeds. Size is not defined.

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
  • StreamError – stream is not seekable and tellable
  • SelectError – neither subcon succeded when parsing or building

Example:

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

Alternative syntax, but requires Python 3.6 or any PyPy:
>>> Select(num=Int32ub, text=CString("utf8"))
exception construct.core.SelectError
class construct.core.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. Embedded fields do not need to (and should not) be named.

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 supports embedding. Embedded semantics dictate, that during instance creation (in ctor), each field is checked for embedded flag, and its subcon members are merged. This changes behavior of some code examples. Only few classes are supported: Struct Sequence FocusedSeq Union LazyStruct, although those can be used interchangably (a Struct can embed a Sequence, or rather its members).

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)
exception construct.core.SizeofError
class construct.core.Slicing(subcon, count, start, stop, step=1, empty=None)

Adapter for slicing a list. Works with GreedyRange and Sequence.

Parameters:
  • subcon – Construct instance, subcon to slice
  • count – integer, expected number of elements, needed during building
  • start – integer for start index (or None for entire list)
  • stop – integer for stop index (or None for up-to-end)
  • step – integer, step (or 1 for every element)
  • empty – object, value to fill the list with, during building

Example:

d = Slicing(Array(4,Byte), 4, 1, 3, empty=0)
assert d.parse(b"\x01\x02\x03\x04") == [2,3]
assert d.build([2,3]) == b"\x00\x02\x03\x00"
assert d.sizeof() == 4
exception construct.core.StopFieldError
class construct.core.StopIf(condfunc)

Checks for a condition, and stops certain classes (Struct Sequence GreedyRange) from parsing or building further.

Parsing and building check the condition, and raise StopFieldError if indicated. Size is undefined.

Parameters:condfunc – bool or context lambda (or truthy value)
Raises:StopFieldError – used internally

Can propagate any exception from the lambda, possibly non-ConstructError.

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)))
exception construct.core.StreamError
class construct.core.StringEncoded(subcon, encoding)

Used internally.

exception construct.core.StringError
class construct.core.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. Embedded fields do not need to (and should not) be named.

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 supports embedding. Embedded semantics dictate, that during instance creation (in ctor), each field is checked for embedded flag, and its subcon members are merged. This changes behavior of some code examples. Only few classes are supported: Struct Sequence FocusedSeq Union LazyStruct, although those can be used interchangably (a Struct can embed a Sequence, or rather its members).

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)
class construct.core.Subconstruct(subcon)

Abstract subconstruct (wraps an inner construct, inheriting its name and flags). Parsing and building is by default deferred to subcon, same as sizeof.

Parameters:subcon – Construct instance
class construct.core.Switch(keyfunc, cases, default=None)

A conditional branch.

Parsing and building evaluate keyfunc and select a subcon based on the value and dictionary entries. Dictionary (cases) maps values into subcons. If no case matches then default is used (that is Pass by default). Note that default is a Construct instance, not a dictionary key. Size is evaluated in same way as parsing and building, by evaluating keyfunc and selecting a field accordingly.

Parameters:
  • keyfunc – context lambda or constant, that matches some key in cases
  • cases – dict mapping keys to Construct instances
  • default – optional, Construct instance, used when keyfunc is not found in cases, Pass is default value for this parameter, Error is a possible value for this parameter
Raises:

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

Can propagate any exception from the lambda, possibly non-ConstructError.

Example:

>>> d = Switch(this.n, { 1:Int8ub, 2:Int16ub, 4:Int32ub })
>>> d.build(5, n=1)
b'\x05'
>>> d.build(5, n=4)
b'\x00\x00\x00\x05'

>>> d = Switch(this.n, {}, default=Byte)
>>> d.parse(b"\x01", n=255)
1
>>> d.build(1, n=255)
b"\x01"
exception construct.core.SwitchError
class construct.core.SymmetricAdapter(subcon)

Abstract adapter class.

Needs to implement _decode() only, for both parsing and building.

Parameters:subcon – Construct instance
exception construct.core.TerminatedError
construct.core.Timestamp(subcon, unit, epoch)

Datetime, represented as Arrow object.

Note that accuracy is not guaranteed, because building rounds the value to integer (even when Float subcon is used), due to floating-point errors in general, and because MSDOS scheme has only 5-bit (32 values) seconds field (seconds are rounded to multiple of 2).

Unit is a fraction of a second. 1 is second resolution, 10**-3 is milliseconds resolution, 10**-6 is microseconds resolution, etc. Usually its 1 on Unix and MacOSX, 10**-7 on Windows. Epoch is a year (if integer) or a specific day (if Arrow object). Usually its 1970 on Unix, 1904 on MacOSX, 1600 on Windows. MSDOS format doesnt support custom unit or epoch, it uses 2-seconds resolution and 1980 epoch.

Parameters:
  • subcon – Construct instance like Int* Float*, or Int32ub with msdos format
  • unit – integer or float, or msdos string
  • epoch – integer, or Arrow instance, or msdos string
Raises:
  • ImportError – arrow could not be imported during ctor
  • TimestampError – subcon is not a Construct instance
  • TimestampError – unit or epoch is a wrong type

Example:

>>> d = Timestamp(Int64ub, 1., 1970)
>>> d.parse(b'\x00\x00\x00\x00ZIz\x00')
<Arrow [2018-01-01T00:00:00+00:00]>
>>> d = Timestamp(Int32ub, "msdos", "msdos")
>>> d.parse(b'H9\x8c"')
<Arrow [2016-01-25T17:33:04+00:00]>
exception construct.core.TimestampError
class construct.core.Transformed(subcon, decodefunc, decodeamount, encodefunc, encodeamount)

Transforms bytes between the underlying stream and the (fixed-sized) subcon.

Parsing reads a specified amount (or till EOF), processes data using a bytes-to-bytes decoding function, then parses subcon using those data. Building does build subcon into separate bytes, then processes it using encoding bytes-to-bytes function, then writes those data into main stream. Size is reported as decodeamount or encodeamount if those are equal, otherwise its SizeofError.

Used internally to implement Bitwise Bytewise ByteSwapped BitsSwapped .

Possible use-cases include encryption, obfuscation, byte-level encoding.

Warning

Remember that subcon must consume (or produce) an amount of bytes that is same as decodeamount (or encodeamount).

Warning

Do NOT use seeking/telling classes inside Transformed context.

Parameters:
  • subcon – Construct instance
  • decodefunc – bytes-to-bytes function, applied before parsing subcon
  • decodeamount – integer, amount of bytes to read
  • encodefunc – bytes-to-bytes function, applied after building subcon
  • encodeamount – integer, amount of bytes to write
Raises:
  • StreamError – requested reading negative amount, could not read enough bytes, requested writing different amount than actual data, or could not write all bytes
  • StreamError – subcon build and encoder transformed more or less than encodeamount bytes, if amount is specified
  • StringError – building from non-bytes value, perhaps unicode

Can propagate any exception from the lambdas, possibly non-ConstructError.

Example:

>>> d = Transformed(Bytes(16), bytes2bits, 2, bits2bytes, 2)
>>> d.parse(b"\x00\x00")
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'

>>> d = Transformed(GreedyBytes, bytes2bits, None, bits2bytes, None)
>>> d.parse(b"\x00\x00")
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
class construct.core.Tunnel(subcon)

Abstract class that allows other constructs to read part of the stream as if they were reading the entrie stream. See Prefixed for example.

Needs to implement _decode() for parsing and _encode() for building.

class construct.core.Union(parsefrom, *subcons, **subconskw)

Treats the same data as multiple constructs (similar to C union) so you can look at the data in multiple views. Fields are usually named (so parsed values are inserted into dictionary under same name). Embedded fields do not need to (and should not) be named.

Parses subcons in sequence, and reverts the stream back to original position after each subcon. Afterwards, advances the stream by selected subcon. Builds from first subcon that has a matching key in given dict. Size is undefined (because parsefrom is not used for building).

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 supports embedding. Embedded semantics dictate, that during instance creation (in ctor), each field is checked for embedded flag, and its subcon members are merged. This changes behavior of some code examples. Only few classes are supported: Struct Sequence FocusedSeq Union LazyStruct, although those can be used interchangably (a Struct can embed a Sequence, or rather its members).

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.

Warning

If you skip parsefrom parameter then stream will be left back at starting offset, not seeked to any common denominator.

Parameters:
  • parsefrom – how to leave stream after parsing, can be integer index or string name selecting a subcon, or None (leaves stream at initial offset, the default), or context lambda
  • *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
  • StreamError – stream is not seekable and tellable
  • UnionError – selector does not match any subcon, or dict given to build does not contain any keys matching any subcon
  • IndexError – selector does not match any subcon
  • KeyError – selector does not match any subcon

Can propagate any exception from the lambda, possibly non-ConstructError.

Example:

>>> d = Union(0, 
...     "raw" / Bytes(8),
...     "ints" / Int32ub[2],
...     "shorts" / Int16ub[4],
...     "chars" / Byte[8],
... )
>>> d.parse(b"12345678")
Container(raw=b'12345678', ints=[825373492, 892745528], shorts=[12594, 13108, 13622, 14136], chars=[49, 50, 51, 52, 53, 54, 55, 56])
>>> d.build(dict(chars=range(8)))
b'\x00\x01\x02\x03\x04\x05\x06\x07'

>>> d = Union(None,
...     "animal" / Enum(Byte, giraffe=1),
... )
>>> d.animal.giraffe
'giraffe'
>>> d = Union(None,
...     "chars" / Byte[4],
...     "data" / Bytes(lambda this: this._subcons.chars.sizeof()),
... )
>>> d.parse(b"\x01\x02\x03\x04")
Container(chars=[1, 2, 3, 4])(data=b'\x01\x02\x03\x04')

Alternative syntax, but requires Python 3.6 or any PyPy:
>>> Union(0, raw=Bytes(8), ints=Int32ub[2], shorts=Int16ub[4], chars=Byte[8])
exception construct.core.UnionError
exception construct.core.ValidationError
class construct.core.Validator(subcon)

Abstract class that validates a condition on the encoded/decoded object.

Needs to implement _validate() that returns a bool (or a truthy value)

Parameters:subcon – Construct instance
construct.core.encodingunit(encoding)

Used internally.