Enumeration to bytes and bytes to enumeration transform.

[plum.enum] Module Reference

The plum.enum module provides the EnumX transform which converts an integer enumeration member into bytes and bytes into an integer enumeration member. This reference page demonstrates creating and using an EnumX transform as well as provides API details.

The examples shown on this page require the following setup:

>>> from enum import IntEnum
>>> from plum.enum import EnumX
>>> from plum.utilities import pack, unpack
>>>
>>> class Register(IntEnum):
...     PC = 0
...     SP = 1
...     R0 = 2
...     R1 = 3
...

Basic Usage

The EnumX transform accepts the following arguments:

enum:associated integer enumeration class
nbytes:format size in bytes (any positive integer)
byteorder:"big" or "little" (default)
signed:True or False (default)
strict:True (default) or False
name:transform name (for representations including dump format column)

For example:

>>> register = EnumX(Register, byteorder="big", nbytes=2, signed=False)

Then use the transform to specify a format when using the pack() and unpack() utility functions or when using other high level transforms. Its advantage over using a IntX transform is that unpacking results in the corresponding enumeration member.

>>> fmt = [register, register]
>>>
>>> unpack(fmt, b'\x00\x00\x00\x01')
[<Register.PC: 0>, <Register.SP: 1>]
>>>
>>> pack([Register.R1, Register.SP], fmt)
b'\x00\x03\x00\x01'

Tip

Use sys.byteorder as the EnumX transform byteorder argument to get the same byte order as the architecture of the machine your script is running on.

Strict vs. Tolerant

Since the register transform did not specify a value for strict, it defaulted to require valid values when packing. The transform raises a PackError for values not within the enumeration:

>>> pack(0xff, fmt=register)
Traceback (most recent call last):
  ...
plum.exceptions.PackError:
<BLANKLINE>
+--------+-------+-------+--------------------+
| Offset | Value | Bytes | Format             |
+--------+-------+-------+--------------------+
|        | 255   |       | Register (IntEnum) |
+--------+-------+-------+--------------------+
<BLANKLINE>
ValueError occurred during pack operation:
<BLANKLINE>
255 is not a valid Register

Similarly, the transforms requires integer values that are associated with a member of the enumeration when unpacking:

>>> unpack(register, b'\x00\xff')
Traceback (most recent call last):
  ...
plum.exceptions.UnpackError:
<BLANKLINE>
+--------+-------+-------+--------------------+
| Offset | Value | Bytes | Format             |
+--------+-------+-------+--------------------+
| 0      | 255   | 00 ff | Register (IntEnum) |
+--------+-------+-------+--------------------+
<BLANKLINE>
ValueError occurred during unpack operation:
<BLANKLINE>
255 is not a valid Register
>>>

To tolerate values not defined within the enumeration, set the strict argument to False when creating the enumeration transform. For example:

>>> register = EnumX(Register, byteorder="big", nbytes=2, signed=False, strict=False)
>>>
>>> pack(0xff, register)
b'\x00\xff'
>>> unpack(register, b'\x00\xff')
255

API Reference

class plum.enum.EnumX(enum: Type[enum.IntEnum], nbytes: int = 1, byteorder: Union[Literal[little], Literal[big]] = 'little', *, signed: bool = False, strict: bool = True, name: Optional[str] = None)

Enumeration to bytes and bytes to enumeration transform.

byteorder

Byte order (“little” or “big”).

enum

Enumeration.

name

Transform format name (for repr and dump “Format” column).

nbytes

Transform format size in bytes.

signed

Signed integer.

strict

Values to pack/unpack must be an enumeration member.

pack(value: Any) → bytes

Pack value as formatted bytes.

Raises:PackError if type error, value error, etc.
pack_and_dump(value: Any) → Tuple[bytes, plum.dump.Dump]

Pack value as formatted bytes and produce bytes summary.

Raises:PackError if type error, value error, etc.
unpack(buffer: bytes) → Any

Unpack value from formatted bytes.

Raises:UnpackError if insufficient bytes, excess bytes, or value error
unpack_and_dump(buffer: bytes) → Tuple[Any, plum.dump.Dump]

Unpack value from bytes and produce packed bytes summary.

Raises:UnpackError if insufficient bytes, excess bytes, or value error