3.4. Conditional Fields#
Conditional fields allow you to define fields in a struct that are included or excluded based on certain conditions. This feature is especially useful when working with versioned formats or optional fields that depend on runtime conditions. You can easily achieve this using context-based lambdas, which are built into the library.
3.4.1. How it works#
By using the with keyword in combination with conditional expressions, you can bind certain fields to a specific condition. This allows you to include or exclude fields dynamically, depending on the value of other fields or context.
Here’s an example demonstrating how to use conditional fields for versioned structs:
@struct
class Format:
version: uint32
# all following fields will be bound to the condition
with this.version == 1:
header: uint8
3.4.2. Key Concepts#
`with` and Conditionals: The
with
keyword is used to define a block of fields that should only be included if the condition evaluates toTrue
. In the example above, the fields insidewith this.version == 1
are included only when theversion
field has a value of1
.`ElseIf` for Multiple Conditions: For multiple conditions, use
ElseIf
rather thanElse
. TheElseIf
construct ensures that the next condition is checked only if the previous one was false. This is safer and more predictable than using a genericElse
clause, which could introduce unintended side effects by executing under unanticipated conditions.
3.4.2.1. Example: Versioned Struct#
Conditional fields are particularly useful when dealing with versioned structs, where the structure of the data may change based on the version number or other factors. For example:
@struct
class Format:
version: uint32
# all following fields will be bound to the condition
with this.version == 1:
length: uint8
extra: uint8
data: Bytes(this.length)
# Use else-if over 'Else' alone
with ElseIf(this.version == 2):
name: CString(16)
data: Prefixed(uint8)
3.4.3. Best Practices#
Avoid Using `Else`: It is strongly recommended to avoid using
Else
for conditional field inclusion, as it can introduce unintended behavior if not properly managed. Instead, always useElseIf
with an inverted condition to ensure more predictable and controlled struct parsing.
Note
When using conditional fields, it’s essential to remember that the struct’s layout can change dynamically depending on the conditions. This flexibility makes it possible to define complex, version-dependent data structures.