pak.types.optional

Types for marshaling data which might exist.

class Optional(elem_type, exists=None)[source]

Bases: Type

A Type which might exist.

Parameters:
  • elem_type (typelike) – The underlying Type.

  • exists (typelike or None or str or function) –

    If a typelike, then the Optional is prefixed by the typelike and its value determines whether or not the Optional exists. This case will be deferred to Optional.PrefixChecked.

    If None, then whether the Optional exists is not checked, and is eagerly tried to be unpacked. This is usually used for Optionals at the end of the buffer. This case will be deferred to Optional.Unchecked.

    If a str, then whether the Optional exists is determined by getting the attribute of the same name from the Packet instance. This case will be deferred to Optional.FunctionChecked.

    If a function, then whether the Optional exists is determined by passing the Packet instance to the function. This case will be deferred to Optional.FunctionChecked.

elem_type = None
exists = None
class PrefixChecked(elem_type, exists)[source]

Bases: Optional

An Optional which exists if its prefix says so.

Parameters:
  • elem_type (typelike) – The underlying Type.

  • exists (typelike) – A boolean Type which prefixes elem_type, determining whether the Optional exists or not.

Examples

>>> import pak
>>> Prefixed = pak.Optional(pak.Int8, pak.Bool)
>>> Prefixed.unpack(b"\x01\x02")
2
>>> Prefixed.pack(2)
b'\x01\x02'
>>>
>>> assert Prefixed.unpack(b"\x00") is None
>>> Prefixed.pack(None)
b'\x00'
class Unchecked(elem_type)[source]

Bases: Optional

An Optional which does not check whether it exists.

Such Optionals are usually placed at the end of raw data.

The Optional does not exist if any Exception is thrown while unpacking.

If a Type.UnsuppressedError is thrown while unpacking, then that Exception will not be suppressed.

Parameters:

elem_type (typelike) – The underlying Type.

Examples

>>> import pak
>>> Unchecked = pak.Optional(pak.Int8)
>>> Unchecked.unpack(b"\x01")
1
>>> Unchecked.pack(1)
b'\x01'
>>>
>>> assert Unchecked.unpack(b"") is None
>>> Unchecked.pack(None)
b''
class FunctionChecked(elem_type, exists)[source]

Bases: Optional

An Optional which exists if a function says so.

The function will be passed the relevant Packet instance, and should return a bool determining whether the Optional exists.

Parameters:
  • elem_type (typelike) – The underlying Type.

  • exists (function or str) –

    If a function, then whether the Optional exists is determined by calling the function with the relevant Packet instance.

    If a str, then a function which gets and returns the attribute named by the str is used as the effective function for the existence of the Optional.

Examples

If a str is used as exists:

>>> import pak
>>> class MyPacket(pak.Packet):
...     exists:   pak.Bool
...     optional: pak.Optional(pak.Int8, "exists")
...
>>> packet = MyPacket.unpack(b"\x01\x02")
>>> packet
MyPacket(exists=True, optional=2)
>>> packet.pack()
b'\x01\x02'
>>>
>>> packet = MyPacket.unpack(b"\x00")
>>> packet
MyPacket(exists=False, optional=None)
>>> packet.pack()
b'\x00'

If a function is used as exists:

>>> import pak
>>> class MyPacket(pak.Packet):
...     flag:     pak.Int8
...     optional: pak.Optional(pak.Int8, lambda p: p.flag == 3)
...
>>> packet = MyPacket.unpack(b"\x03\x02")
>>> packet
MyPacket(flag=3, optional=2)
>>> packet.pack()
b'\x03\x02'
>>>
>>> packet = MyPacket.unpack(b"\x01")
>>> packet
MyPacket(flag=1, optional=None)
>>> packet.pack()
b'\x01'