.. _tutorial-bitfield:

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.

Syntax
------

In *Caterpillar*, BitFields are defined using the :code:`@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:

.. code-block:: python
    :caption: Implementing the `chunk-naming <https://www.w3.org/TR/png/#5Chunk-naming-conventions>`_ 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 :code:`ChunkOptions` class is assigned
a specific number of bits:

- The first two bits (:code:`_`) are unused (or "unnamed").
- The :code:`ancillary` field uses 1 bit, representing a flag.
- Other fields like :code:`private`, :code:`reserved`, and :code:`safe_to_copy` are allocated 1 or 2 bits as needed.

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

.. code-block:: text

    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:
- :code:`u` = unnamed bits (unused)
- :code:`a` = added bits
- :code:`f0`, :code:`f1`, :code:`f2`, :code:`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.