3.2.1.4. Bit-field#

A Bit-field, despite its name suggesting a field of bits, is a powerful structure designed for detailed byte inspection. Similar to other structures, it is a finite collection of named fields. This section will introduce potential challenges associated with the implementation of a Bitfield and explains its behavior.

Changed in version 2.5.0: Completely reworked the internal Bitfield behaviour, model and processing.

Concept#

Each Bitfield instance maintains a sequence of bitfield groups, where each group contains a collection of sized fields. A bitfield group may consist of either multiple entries (i.e., any types that can be converted to an integral type) or a single _StructLike object. For example, consider the following bitfield definition:

@bitfield
class Format:
    a1: 2
    a2: 1
    _ : 0
    b1: char
    c1: uint32

This Bitfield definition will generate three distinct bitfield groups (labeled here as groups a, b, and c). By default, bitfields use 8-bit alignment, leading to the following layout:

Group      Pos       Bits
a          0x00      8
b          0x01      8
c          0x02      32

Internally, only the first group requires special bit-level parsing. The remaining groups (b and c) are treated as standard structures since they span full bytes or words without sub-byte alignment. This dynamic grouping mechanism allows leveraging full struct-like class definitions within bitfields.

Syntax#

This new approach enables more complex and expressive bitfield definitions. The annotation syntax is therefore extended as follows:

name : bits - field (optional) (1)
name : 0 (2)
name : field-or-action (3)
name : ( field , factory ) (4)
name : ( bits , factory (optional) , options (optional) ) (5)

Each identifier named above is bound to certain constraints:

name - Any valid Python attribute name.
bits - Any valid positive integer starting from 0.
field - Any valid field definition for a struct resulting in a _StructLike that implements the subtract-operation resulting in a Field instance.
field-or-action - Any valid field definition for a struct resulting or an object implementing the _ActionLike protocol.
factory - Either a target Python type to use as factory or an instance of BitfieldValueFactory.
options - One or more options represented either as flags or instances of SetAlignment.

What that syntax allows can be seen in the following example:

Bit-field definition using all syntax rules#
@bitfield
class Format: #                                               -.
    # Any annotation that can be converted by a TypeConverter  | 1. Group
    # into as _StructLike object is allowed.                   | (3 Bytes)
    magic: b"foo" # bytes                                     -'

    # Syntax according to (1) and (2)                         -.
    version : 4 # int                                          | 2. Group
    state   : 3 # int                                          | (1 Byte / 8 Bits)
    _       : 0 # ignored/removed                             -'

    # Extended Syntax (5)
    flag1 : (1, SetAlignment(16))     # bool, new alignment   -.
    flag2 : 1                         # bool                   | 3. Group
    name  : (12, CharFactory)         # str                    | (2 Bytes / 16 Bits)
    type  : (2, SimpleEnum, EndGroup) # SimpleEnum            -'

Processing Rules#

Based on the previously defined syntax, some processing constraints were derived:

  • Rule 1.:
    • Default alignment is 1 byte (8 bits).

    • Zero (0) bits are prohibited.

    • If followed by a (2) declaration, the remaining bits in the current byte are padded.

    • If a <field> is provided:
      • typeof(<field>) is used to infer the factory.

      • getbits() and sizeof() determine the field’s alignment.

    • If a custom alignment is configured in the Bitfield constructor, inferred alignment is ignored unless the field includes the B_OVERWRITE_ALIGNMENT option.

    • If the B_GROUP_END option is set, the current group is finalized and a new one is started.

  • Rule 2.:
    • This rule forces alignment to the next byte boundary.

    • The field is ignored during final class generation (name is discarded).

    • The current group is finalized unless the bitfield is configured with B_GROUP_KEEP

  • Rule 3.:
    • Equivalent to struct-like class field definitions.

    • Automatically implies a rule 2 alignment.

    • Always finalizes the current group regardless of B_GROUP_KEEP.

  • Rule 4.:
    • Extension of (1).

    • Explicitly defines a conversion factory for the field.

    • The factory must be:
      • A built-in type (e.g., int, bool) supporting __int__, or

      • A type or instance of BitfieldValueFactory.

  • Rule 5.:
    • Builds upon (4) with support for options.

    • Options can be passed as a list or single element.

    • Supported Options:
      • NewGroup: Aligns the current group, starts a new one, and adds the entry to it.

      • EndGroup: Adds the entry to the current group, then aligns it.

      • SetAlignment: Changes the current working alignment.

    • Note: Option order affects behavior and must be considered carefully.