Core API: Lazy equivalents

construct.LazyStruct(*subcons, **kw)

Equivalent to Struct construct, however fixed size members are parsed on demand, others are parsed immediately. If entire struct is fixed size then entire parse is essentially one stream seek.

See also

Equivalent to Struct().

Warning

Struct members that depend on earlier context entries do not work properly, because since Struct is lazy, there is no guarantee that previous members were parsed and put into context dictionary.

construct.LazySequence(*subcons, **kw)

Equivalent to Sequence construct, however fixed size members are parsed on demand, others are parsed immediately. If entire sequence is fixed size then entire parse is essentially one seek.

See also

Equivalent to Sequence().

construct.LazyRange(min, max, subcon)

Equivalent to Range construct, but members are parsed on demand. Works only with fixed size subcon. Entire parse is essentially one stream seek.

See also

Equivalent to Range().

construct.OnDemand(subcon)

Allows for lazy parsing of one field. When parsing, it will return a parameterless function that when called, will return the parsed value. Object is cached after first parsing, so non-deterministic subcons will be affected. Works only with fixed size subcon.

Parameters:subcon – the subcon to read/write on demand, must be fixed size

Example:

>>> d = OnDemand(Byte)
>>> d.parse(b"\xff")
<function OnDemand._parse.<locals>.<lambda> at 0x7fdc241cfc80>
>>> _()
255
>>> d.build(255)
b'\xff'

Can also re-build from the lambda returned at parsing.

>>> d.parse(b"\xff")
<function OnDemand._parse.<locals>.<lambda> at 0x7fcbd9855f28>
>>> d.build(_)
b'\xff'
construct.LazyBound(subconfunc)

Lazy-bound construct that binds to the construct only at runtime. Useful for recursive data structures (like linked lists or trees), where a construct needs to refer to itself (while it does not exist yet).

Parameters:subconfunc – a context function returning a Construct (derived) instance, can also return Pass or itself

Example:

>>> d = Struct(
...     "value"/Byte,
...     "next"/If(this.value > 0, LazyBound(lambda ctx: d)),
... )
...
>>> d.parse(b"\x05\x09\x00")
Container(value=5)(next=Container(value=9)(next=Container(value=0)(next=None)))
...
>>> print(d.parse(b"\x05\x09\x00"))
Container:
    value = 5
    next = Container:
        value = 9
        next = Container:
            value = 0
            next = None