3.6. Bitfields#

Attention

This section is still under development.

BitFields are a specialized feature in Caterpillar that allow you to define fields at the bit level within a struct. This is particularly useful when dealing with compact binary formats, such as network protocols, file formats, or hardware interfaces where each bit has a specific meaning.

BitFields allow you to specify the number of bits allocated for each field and provide the ability to fine-tune how data is stored and retrieved from a binary stream. This feature is useful when you need to work with bit-level manipulations, such as when defining flags, options, or small data values packed into a single byte or multiple bytes.

3.6.1. Syntax#

In Caterpillar, BitFields are defined using the @bitfield decorator, and the individual fields are specified with their respective bit widths.

One practical example of using BitFields is implementing the chunk-naming convention for PNG files. Here’s how you might define the options for a chunk using a bitfield structure:

Implementing the chunk-naming convention#
@bitfield(options={S_DISCARD_UNNAMED})
class ChunkOptions:
    _            : 2        # <-- first two bits are not used
    ancillary    : 1        # f0
    _1           : 0
    _2           : 2
    private      : 1        # <-- the 5-th bit (from right to left)
    _3           : 0
    _4           : 2
    reserved     : 1        # f2
    _5           : 0        # <-- padding until the end of this byte
    _6           : 2
    safe_to_copy : 1        # f3

In the example above, each field within the ChunkOptions class is assigned a specific number of bits:

  • The first two bits (_) are unused (or “unnamed”).

  • The ancillary field uses 1 bit, representing a flag.

  • Other fields like private, reserved, and safe_to_copy are allocated 1 or 2 bits as needed.

Here’s a breakdown of how the bits are laid out in memory:

byte     :     0        1       2        3
bit      : 76543210 76543210 76543210 76543210
----------------------------------------------
breakdown: 00100000 00100000 00100000 00100000
           \/|\___/ \/|\___/ \/|\___/ \/|\___/
           u f0 a   u f1 a   u f2  a  u f3 a

Where: - u = unnamed bits (unused) - a = added bits - f0, f1, f2, f3 = corresponding fields (ancillary, private, reserved, safe_to_copy)

Each bit or group of bits is allocated to a specific field, allowing you to pack multiple flags or small values into a single byte or a group of bytes.