3.2.3. Processing-related Types#
3.2.3.1. Field#
The next core element of this library is the Field. It serves as a context storage to store configuration data
about a struct. Even sequences and structs can be used as fields. The process is straightforward: each custom operator
creates an instance of a Field with the applied configuration value. Most of the time, this value can be
static or a Context Lambdas. A field implements basic behavior that should not be duplicated, such as
conditional execution, exception handling with default values, and support for a built-in switch-case structure.
As mentioned earlier, some primitive structs depend on being linked to a Field. This is because all
configuration elements are stored in a Field instance rather than in the target struct instance. More
information about each supported configuration can be found in Operators.
3.2.3.2. Greedy#
This library provides direct support for greedy parsing. Leveraging Python’s syntactic features, this special form
of parsing is enabled using the Ellipsis (...). All previously introduced structs implement greedy parsing
when enabled.
>>> field = uint8[...]
This special type can be used in places where a length has to be specified. Therefore, it can be applied to all array
[] declarations and constructors that take the length as an input argument, such as CString, for
example.
>>> field = Field(CString(...))
>>> unpack(field, b"abcd\x00")
'abcd'
3.2.3.3. Prefixed#
In addition to greedy parsing, this library supports prefixed packing and unpacking as well. With prefixed, we refer
to the length of an array of elements that should be parsed. In this library, the slice class is to achieve a
prefix option.
>>> field = CString[uint32::]
3.2.3.4. Context#
The context is another core element of this framework, utilized to store all relevant variables needed during the
process of packing or unpacking objects. The top-level unpack() and pack() methods are designed to
create the context themselves with some pre-defined (internal) fields.
Implementation Note
Context objects are essentially dict objects with enhanced capabilities. Therefore, all
operations supported on dictionaries are applicable.
The context enables special attribute-like access using getattr if the attribute wasn’t defined in the
instance directly. All custom attributes are stored in the dictionary representation of the instance.
- CTX_PARENT = "_parent"#
All
Contextinstances SHOULD contain a reference to the parent context. If the returned reference isNone, it can be assumed that the current context is the root context. If this attribute is set, it MUST point to aContextinstance.
- CTX_OBJECT = "_obj"#
When packing or unpacking objects, the current object attributes are stored within the object context. This is a special context that allows access to previously parsed fields or attributes of the input object. To minimize the number of calls using this attribute, a shortcut named
thiswas defined, which automatically inserts a path to the object context.
- CTX_STREAM = "_io"#
The input or output stream MUST be set in each context instance to prevent access errors on missing stream objects.
See also
Discussion on Github why this attribute has to be set in every context instance.
- CTX_PATH = "_path"#
Although it is optional to provide the current parsing or building path, it is recommended. All nesting structures implement a behavior that automatically adds a sub-path while packing or unpacking. Special names are
"<root>"for the starting path and"<NUMBER>"for greedy sequence elements.
- CTX_FIELD = "_field"#
In case a struct is linked to a field, the
Fieldinstance will always set this context variable to be accessible from within the underlying struct.
- CTX_INDEX = "_index"#
When packing or unpacking collections of elements, the current working index is given under this context variable. This variable is set only in this specific situation.
- CTX_VALUE = "_value"#
In case a switch-case statement is activated in a field, the context will receive the parsed value in this context variable temporarily.
- CTX_POS = "_pos"#
Currently undefined.
- CTX_OFFSETS = "_offsets"#
Internal use only: This special member is only set in the root context and stores all packed objects that should be placed at an offset position.
- CTX_ROOT = "_root"#
Added in version 2.5.0.
Special attribute set to specify the root context. If this attribute is not present, the current
Contextinstance will be returned.
3.2.3.5. Context path#
The path of a context is a specialized form of a Context Lambdas and supports lazy evaluation of most
operators (conditional ones excluded). Once called, they try to retrieve the requested value from within
the given Context instance. Below is a list of default paths designed to provide a relatively easy
way to access the context variables.
- ctx = ""#
This special path acts as a wrapper to access all variables within the top-level
Contextobject.
- this = "_obj"#
As described before, a special object context is created when packing or unpacking structs that store more than one field.
- parent = "_parent._obj"#
A shortcut to access the object context of the parent context.