Core API: Streaming

construct.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'
construct.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
construct.OffsettedEnd(endoffset, subcon)

Parses all bytes in the stream till EOF plus a negative endoffset is reached.

This is useful when GreedyBytes (or any other greedy construct) is followed by a fixed-size footer.

Parsing determines the length of the stream and reads all bytes till EOF plus endoffset is reached, then defers to subcon using new BytesIO with said bytes. Building defers to subcon as-is. Size is undefined.

Parameters:
  • endoffset – integer or context lambda, only negative offsets or zero are allowed

  • subcon – Construct instance

Raises:
  • StreamError – could not read enough bytes

  • StreamError – reads behind the stream (if endoffset is positive)

Example:

>>> d = Struct(
...     "header" / Bytes(2),
...     "data" / OffsettedEnd(-2, GreedyBytes),
...     "footer" / Bytes(2),
... )
>>> d.parse(b"\x01\x02\x03\x04\x05\x06\x07")
Container(header=b'\x01\x02', data=b'\x03\x04\x05', footer=b'\x06\x07')
construct.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'
construct.Tell()

Tells the stream.

Parsing and building return current stream offset using using stream.tell(). Size is defined as 0 because parsing and building does not consume or add into the stream.

Tell is useful for adjusting relative offsets to absolute positions, or to measure sizes of Constructs. To get an absolute pointer, use a Tell plus a relative offset. To get a size, place two Tells and measure their difference using a Compute field. However, its recommended to use RawCopy instead of manually extracting two positions and computing difference.

Raises:

StreamError – stream is not tellable

Example:

>>> d = Struct("num"/VarInt, "offset"/Tell)
>>> d.parse(b"X")
Container(num=88, offset=1)
>>> d.build(dict(num=88))
b'X'
construct.Pass()

No-op construct, useful as default cases for Switch and Enum.

Parsing returns None. Building does nothing. Size is 0 by definition.

Example:

>>> Pass.parse(b"")
None
>>> Pass.build(None)
b''
>>> Pass.sizeof()
0
construct.Terminated()

Asserts end of stream (EOF). You can use it to ensure no more unparsed data follows in the stream.

Parsing checks if stream reached EOF, and raises TerminatedError if not. Building does nothing. Size is defined as 0 because parsing and building does not consume or add into the stream, as far as other constructs see it.

Raises:

TerminatedError – stream not at EOF when parsing

Example:

>>> Terminated.parse(b"")
None
>>> Terminated.parse(b"remaining")
construct.core.TerminatedError: expected end of stream