binobj.fields.containers module

Fields used for forming more complex structures with other fields.

class Array(*_args: Any, **kwargs: Any)

Bases: Field[List[Optional[T]]]

An array of other serializable objects.

Parameters:
  • component (Field) – The component this array is comprised of. Must be an instance.

  • count

    Optional. Some way of indicating the number of elements in this array. The value for this argument can be one of the following:

    • An integer. The array always contains this many elements.

    • A Field instance that must 1) be an integer; 2) occur before this array in the same struct.

    • A string naming a field fitting the above criteria. You’ll need this if your size field’s name is a Python keyword.

  • halt_check (callable) – A function taking five arguments. See should_halt() for the default implementation. Subclasses can override this function if desired to avoid having to pass in a custom function every time.

Changed in version 0.3.0: count can now be a Field or string.

Changed in version 0.6.1: to_stream() and to_bytes() throw an ArraySizeError if count is set and the iterable passed in is too long. Due to a bug it used to be ignored when dumping.

Changed in version 0.7.0: size is set if component.size is defined and count is an integer constant.

const: T | _Undefined

The fixed value of a field, if applicable.

This is mostly useful for fields that act as magic numbers or reserved fields in a struct that should be set to nulls.

discard: bool

If True, indicates that a field should be discarded when read.

This is best used for filler fields that are of no use to the application but are nonetheless important to ensure the proper layout of the struct.

get_final_element_count(field_values: Mapping[str, Any]) int | None

Calculate the number of elements in the array based on other fields’ values.

Parameters:

field_values (dict) – A dict mapping field names to their deserialized values. It doesn’t need to have every value in the struct; if count references a field, it only requires that field to be present here.

Returns:

The expected number of elements in this array, or None if the array doesn’t have a fixed size.

Return type:

int

New in version 0.6.1.

Changed in version 0.8.0: Throws a ConfigurationError if this field’s count is a Field but doesn’t have an assigned name.

name: str

The name of the field.

Technical Note: This attribute can only be None if the field was created without passing a value for name to the constructor and the field has never been bound to a struct. Since this is highly unlikely in normal usage, this attribute is declared as str rather than Optional[str].

offset: int | None
static should_halt(seq: Array[T], stream: BinaryIO, values: List[T | None], context: Any, loaded_fields: Mapping[str, Any]) bool

Determine if the deserializer should stop reading from the input.

This function should return True to indicate loading for this field should stop, or False to continue adding elements.

The default implementation does the following:

  • If count is an integer, it compares count against the length of values. If len(values) is equal to or more than count it’ll return True (halt), False otherwise.

  • If count is a Field, that field should already have been loaded and in loaded_fields. The expected array size is taken from there, and compared as above.

  • If count is a string, it’s the name of a field already loaded and in loaded_fields. The expected array size is taken from there, and compared as above.

  • Otherwise, the function assumes the array ends at EOF and only returns True if there’s no more data in the stream.

Subclasses’ implementations must handle all four cases.

Parameters:
  • seq (Array) – The sequence being checked.

  • stream (BinaryIO) – The data stream to read from. Except in rare circumstances, this is the same stream that was passed to from_stream(). The stream pointer should be returned to its original position when the function exits.

  • values (list) – A list of the objects that have been deserialized so far. In general this function should not modify the list. A possible exception to this rule is to remove a sentinel value from the end of the list.

  • context – The context object passed to from_stream().

  • loaded_fields (dict) – The fields in the struct that have been loaded so far.

Returns:

True if the deserializer should stop reading, False otherwise.

Return type:

bool

Changed in version 0.8.0: The default implementation now throws UndefinedSizeError if the length of the array couldn’t be determined. Previously this would crash with a TypeError.

class Nested(*_args: Any, **kwargs: Any)

Bases: Field[TStruct]

Used to nest one struct inside of another.

Parameters:

struct_class (Type[Struct]) – The struct class to wrap as a field. Not an instance!

class Address(Struct):
    ...

class Person(Struct):
    name = fields.StringZ()
    address = fields.Nested(Address)

Changed in version 0.7.0: size is set if the struct passed in is of fixed size. Prior to 0.7.0, Person.get_size() would be None even if Address.get_size() returned a value. Now the sizes are the same.

const: T | _Undefined

The fixed value of a field, if applicable.

This is mostly useful for fields that act as magic numbers or reserved fields in a struct that should be set to nulls.

discard: bool

If True, indicates that a field should be discarded when read.

This is best used for filler fields that are of no use to the application but are nonetheless important to ensure the proper layout of the struct.

name: str

The name of the field.

Technical Note: This attribute can only be None if the field was created without passing a value for name to the constructor and the field has never been bound to a struct. Since this is highly unlikely in normal usage, this attribute is declared as str rather than Optional[str].

offset: int | None
class Union(*_args: Any, **kwargs: Any)

Bases: Field[Any]

A field that can be one of several different types of structs or fields.

Parameters:
  • choices – One or more Struct classes or Field instances that can be used for loading and dumping.

  • load_decider (callable) –

    A function that decides which Struct class or Field instance to use for loading the input. It must take four arguments:

    • stream: The stream being loaded from.

    • classes: A list of classes that can be used for loading.

    • context: The context object to pass directly to the loader selected from classes.

    • loaded_fields: A dictionary of the fields that have already been loaded. This is guaranteed to not be None.

  • dump_decider (callable) –

    A function that decides which Struct class or Field instance to use for dumping the given data. It must take four arguments:

    • data: The data to dump. This can be any type.

    • classes: A list of classes that can be used for dumping.

    • context: The context object to pass directly to the dumper selected from classes.

    • all_fields: A dictionary of the fields about to be dumped. This is guaranteed to not be None.

Usage with Structs:

def load_decider(stream, classes, context, loaded_fields):
    data_type_id = loaded_fields['data_type']
    return classes[data_type_id]

def dump_decider(data, classes, context, all_fields):
    data_type_id = all_fields['data_type']
    return classes[data_type_id]

class MyStruct(Struct):
    data_type = UInt8()
    data = Union(UserInfo, FileInfo, SystemInfo,
                 load_decider=load_decider, dump_decider=dump_decider)

Usage with Fields:

class FieldsUnionContainer(binobj.Struct):
    data_type = fields.UInt8()
    item = fields.Union(fields.StringZ(),
                        fields.UInt16(endian='little'),
                        load_decider=fields_load_decider,
                        dump_decider=fields_dump_decider)

New in version 0.3.0.

const: T | _Undefined

The fixed value of a field, if applicable.

This is mostly useful for fields that act as magic numbers or reserved fields in a struct that should be set to nulls.

discard: bool

If True, indicates that a field should be discarded when read.

This is best used for filler fields that are of no use to the application but are nonetheless important to ensure the proper layout of the struct.

name: str

The name of the field.

Technical Note: This attribute can only be None if the field was created without passing a value for name to the constructor and the field has never been bound to a struct. Since this is highly unlikely in normal usage, this attribute is declared as str rather than Optional[str].

offset: int | None