4.11.4 Aligning struct fields

Another kind of esoteric padding happens when certain fields in entities are required to be aligned to some particular alignment. For example, suppose that the flags field in the packets used in the previous sections is required to always be aligned to 4 bytes regardless of the size of the payload. This would be a common requirement if the format is intended to be implemented in systems where data is to be accessed using its “natural” alignment.

Using explicit fields for both the payload and the additional padding, we could come with:

type Packet =
  struct
  {
    offset<uint<32>,B> payload_size;
    byte[payload_size] payload;
    byte[alignto (OFFSET, 4#B)] padding;
    int flags;
  };

Where alignto is a little function defined in the Poke standard library, like this:

fun alignto = (uoff64 offset, uoff64 to) uoff64:
{
  return (to - (offset % to)) % to;
}

Alternatively, using the labels approach (which is generally better as we discussed in the last section) the definition would become:

type Packet =
  struct
  {
    offset<uint<32>,B> payload_size;:
    var payload_offset = OFFSET;
    int flags @ OFFSET + payload_size + alignto (payload_size, 4#B);

    method get_payload_offset = off64:
    {
      return payload_offset;
    }
  };

In this case, the payload space is still completely characterized by the payload_size field and the get_payload_offset method.