You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
In embedded systems, binary file formats, and network protocols, space is at a premium. Instead of using a whole int for a boolean flag, programmers often pack multiple small values into a single byte. For example, a single 8-bit value might store a 3-bit version number, a 1-bit status flag, and a 4-bit command code.
In C, this is handled via Bitfields. In standard Perl, you would have to use complex bitwise math (>>, &, |). In Affix, you can define these fields directly in your Struct and let the JIT engine handle the math for you.
The Recipe
We will build a parser for a hypothetical hardware "Control Register."
1. The | Operator
When used inside a Struct definition, the | operator specifies the bit-width of a field.
mode=> UInt8 | 3
This tells Affix: "The field mode is part of an unsigned 8-bit integer, but only occupies 3 bits."
2. Automatic Masking and Shifting
When you write $reg->{mode} = 5, Affix does the following under the hood:
Reads the current byte from memory.
Clears the 3 bits belonging to mode using a bit-mask (0xF1).
Shifts the value 5 to the correct bit-position.
Bitwise-ORs the result and writes the byte back to memory.
You get all the convenience of a high-level hash with the efficiency of hand-tuned C bitwise math.
3. Zero-Copy Views
By using cast on a string (or a malloc'd pointer), we create a Live View. Modifying the hash keys modifies the underlying memory immediately. This is exactly how you would write a device driver that interacts with memory-mapped hardware registers.
Kitchen Reminders
Endianness
Bitfield ordering is platform-dependent. Most compilers (GCC, Clang, MSVC) pack bits from the least significant bit (LSB) to the most significant bit (MSB) on x86_64, but this can vary on ARM or PowerPC. Always check your hardware manual!
Type Matching
Ensure the base type (e.g., UInt8) matches the total width of the bits you are packing. If you pack 12 bits into a UInt8, Affix will correctly overflow into the next byte, but your C compiler might do something different.
Reserved Fields
Even if you don't use certain bits, you should include them in your struct definition (like the reserved field above) to ensure the subsequent fields are shifted to the correct bit offsets.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
In embedded systems, binary file formats, and network protocols, space is at a premium. Instead of using a whole
intfor a boolean flag, programmers often pack multiple small values into a single byte. For example, a single 8-bit value might store a 3-bit version number, a 1-bit status flag, and a 4-bit command code.In C, this is handled via Bitfields. In standard Perl, you would have to use complex bitwise math (
>>,&,|). In Affix, you can define these fields directly in yourStructand let the JIT engine handle the math for you.The Recipe
We will build a parser for a hypothetical hardware "Control Register."
How It Works
1. The
|OperatorWhen used inside a
Structdefinition, the|operator specifies the bit-width of a field.This tells Affix: "The field
modeis part of an unsigned 8-bit integer, but only occupies 3 bits."2. Automatic Masking and Shifting
When you write
$reg->{mode} = 5, Affix does the following under the hood:modeusing a bit-mask (0xF1).5to the correct bit-position.You get all the convenience of a high-level hash with the efficiency of hand-tuned C bitwise math.
3. Zero-Copy Views
By using
caston a string (or amalloc'd pointer), we create a Live View. Modifying the hash keys modifies the underlying memory immediately. This is exactly how you would write a device driver that interacts with memory-mapped hardware registers.Kitchen Reminders
Endianness
Bitfield ordering is platform-dependent. Most compilers (GCC, Clang, MSVC) pack bits from the least significant bit (LSB) to the most significant bit (MSB) on x86_64, but this can vary on ARM or PowerPC. Always check your hardware manual!
Type Matching
Ensure the base type (e.g.,
UInt8) matches the total width of the bits you are packing. If you pack 12 bits into aUInt8, Affix will correctly overflow into the next byte, but your C compiler might do something different.Reserved Fields
Even if you don't use certain bits, you should include them in your struct definition (like the
reservedfield above) to ensure the subsequent fields are shifted to the correct bit offsets.All reactions